该程序能够编辑所选对象的属性。
这是通过ViewModel 上的SelectedObject属性实现的。
问题如下。如果我选择一个对象,编辑它的属性并在 current 中单击TabItem,那么属性就会更新。但是,如果我编辑属性并且没有从文本字段中移除光标,而是切换到另一个选项卡,则不会保存属性中的更改。
安装UpdateSourceTrigger=PropertyChanged对我不起作用。正好需要LostFocus。
如何解决?
我画了一个反映问题的例子。
代码隐藏:
public class PersonVm : BaseVm
{
private string _name;
private string _lastname;
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public string Lastname
{
get => _lastname;
set
{
_lastname = value;
OnPropertyChanged();
}
}
}
public class MainVm : BaseVm
{
private PersonVm _selectedPerson;
public MainVm()
{
Class1.Add(new PersonVm { Name = "Алексей", Lastname = "Алексеев" });
Class1.Add(new PersonVm { Name = "Иван", Lastname = "Иванов" });
Class2.Add(new PersonVm { Name = "Петр ", Lastname = "Петров" });
Class2.Add(new PersonVm { Name = "Николай", Lastname = "Николаев" });
}
public ObservableCollection<PersonVm> Class1 { get; } = new ObservableCollection<PersonVm>();
public ObservableCollection<PersonVm> Class2 { get; } = new ObservableCollection<PersonVm>();
public PersonVm SelectedPerson
{
get => _selectedPerson;
set
{
_selectedPerson = value;
OnPropertyChanged();
}
}
}
XAML:
<Window.Resources>
<DataTemplate x:Key="DataTemplate">
<ListBox ItemsSource="{Binding}"
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.SelectedPerson}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Lastname}"
Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TabControl>
<TabItem Header="Class1"
Content="{Binding Class1}"
ContentTemplate="{StaticResource DataTemplate}" />
<TabItem Header="Class2"
Content="{Binding Class2}"
ContentTemplate="{StaticResource DataTemplate}" />
</TabControl>
<StackPanel Grid.Column="1">
<TextBlock Text="Имя" />
<TextBox Text="{Binding SelectedPerson.Name}" />
<TextBlock Text="Фамилия" />
<TextBox Text="{Binding SelectedPerson.Lastname}" />
</StackPanel>
</Grid>

目前,事实证明,当事件发生时,
LostFocus绑定不再存在,因此它不会触发。在所有PreviewXXX事件中,它TextBox只有PreviewLostKeyboardFocus,如果您订阅它并使用调试器查看其中的内容Text,那么我们将看到它仍然具有绑定,因此该事件将适合我们。实际上,让我们尝试在订阅者中强制进行绑定更新,将以下代码添加到处理程序中:
你会看到一切都如你所愿。
可以做些什么呢?例如,您可以为所有必要的 添加事件处理程序
TextBox,或实现TextBox具有此类行为的后继者,或者最后, makeAttached Behavior。我认为第一个选项不好,因为。有必要在我们需要
TextBox此类行为的所有窗口/控件中添加此类处理程序,如果TextBox我们中的某些人突然需要此事件的另一个处理程序,我们将不得不将其从代码中挂起。因此,我将展示最后两个选项。
继承人
TextBox,一切都非常简单,我创建了这个类:一切。
TextBox这已经有效,使用它来代替标准就足够了local:MyTextBox。但是这种方法有一个缺点 - 如果您为标准样式设置样式TextBox,那么这些自定义样式将不会定期选择样式,它们必须单独设置样式,尽管实际上我们有相同的样式TextBox。因此,最优化的解决方案似乎是做出附加行为。
将程序集连接到项目
System.Windows.Interactivity并创建一个类:现在在 XAML 中,添加命名空间:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"在正确的地方
TextBox指定这种行为:PS.:值得注意的是,如果自上次更新以来没有任何更改,该技术足够智能,不会更新相同的绑定
Binding。WPF因此,我们不需要采取任何额外的措施来禁用更新绑定LostFocus,它永远不会在那里更新,更新现在总是发生在PreviewLostKeyboardFocus