c# - WPF 绑定不更新 XAML 但调用了 PropertyChanged
问题描述
我正在尝试将 XAML 中 WPF UI 元素的可见性绑定到我的视图模型 ( MainViewModel.DisplayPopup
) 的属性,该属性是从另一个视图模型 ( ContactViewModel
) 的属性更新的,该视图模型 ( ) 是此类 ( MainViewModel
) 的属性。该类BaseViewModel
扩展INotifyPropertyChanged
并使用了一个 Nuget 包,该包在每个属性的设置器中自动调用 PropertyChanged 事件。
这是我的视图模型代码:
public class MainViewModel : BaseViewModel
{
public ObservableCollection<ContactViewModel> TankItems {get; set; }
public bool DisplayPopup
{
get => TankItems.Any(contact => contact.DisplayPopup);
}
public MainViewModel() : base()
{
TankItems = new ObservableCollection<ContactViewModel>();
TankItems.Add(new ContactViewModel());
TankItems.Add(new ContactViewModel());
}
}
public class ContactViewModel : BaseViewModel
{
private bool _isSelected = false;
public bool DisplayPopup {get; set; } = false;
public bool IsSelected {get => _isSelected; set { _isSelected = value; DisplayPopup = value;
}
这是我的 XAML:
<ListBox Grid.Column="0" ItemsSource="{Binding TankItems}" SelectionChanged="List_SelectionChanged">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</ListBox.Style>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="Test" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Border BorderBrush="Orange" BorderThickness="3" Grid.Column="1">
<TextBlock Text="{Binding DisplayPopup}" /> <!-- Stays as false -->
</Border>
我期望发生的是当我单击其中一个ListBox
项目时,DisplayPopup
变为true
,但它保持不变。但是,如果我记录我的值,((MainViewModel)DataContext).DisplayPopup)
我会得到正确的值 -false
在开始时,然后true
在更改选择时。
为什么绑定值不更新?
更新
这是BaseViewModel
使用Fody PropertyChanged的
[AddINotifyPropertyChangedInterfaceAttribute]
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
解决方案
绑定坦克项目中的选定状态
您的代码中有多个问题。让我们从ContactViewModel
.
public bool IsSelected {get => _isSelected; set { _isSelected = value; DisplayPopup = value;
该DisplayPopup
属性是多余的,因为它具有与 相同的状态IsSelected
,请将其删除。
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</ListBox.Style>
此 XAML 是错误的。您必须绑定IsSelected
a 的属性ListBoxItem
,而不是ListBox
. 另外,您绑定到 上的IsSelected
属性MainViewModel
,因为这是DataContext
这里。该属性不存在,因此绑定将不起作用。而是使用ItemContainerStyle
.
<ListBox.ItemContainerStyle>SelectedTankItem
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListBox.ItemContainerStyle>
更新显示弹出属性
如果选择了任何项目,您想要设置DisplayPopup
为。上面的 item 容器样式会设置your 的属性,但不会自动触发in的属性更改。因此,“Text”绑定永远不会更新它的值。MainViewModel
true
IsSelected
ContactViewModel
DisplayPopup
MainViewModel
要解决此问题,请将DisplayPopup
属性MainViewModel
设置为简单的 get-set 属性。你不需要计算它。创建第二个属性来SelectedItem
绑定ListBox
in MainViewModel
。This property will get set, when the selection changes.
public bool DisplayPopup { get; set; }
public ContactViewModel SelectedTankItem { get; set; }
此外,创建一个名为OnSelectedTankItemChanged
您设置DisplayPopup
属性的方法,具体取决于SelectedTankItem
. 当发生变化时,Fody 框架会自动调用此方法SelectedTankItem
。
public void OnSelectedTankItemChanged()
{
DisplayPopup = SelectedTankItem != null;
}
然后将SelectedItem
你的绑定ListBox
到SelectedTankItem
.
<ListBox Grid.Column="0" ItemsSource="{Binding TankItems}" SelectedItem="{Binding SelectedTankItem}">
<!-- ...other code. -->
</ListBox>
您可以通过删除属性更改代码来简化基本视图模型。您不需要它,因为该属性将导致 Fody 为您实现它。
[AddINotifyPropertyChangedInterfaceAttribute]
public class BaseViewModel : INotifyPropertyChanged
{
}
推荐阅读
- scala - 我们如何对 rdd 中的多个值进行分组?
- r - 在数据帧中使用 R 中的时间插值时出现 na.spline 的问题
- angular - Angular 8 记住数据
- reactjs - 具有多个输入和状态更改的 Reactjs 表单
- angular - 使用严格的 Content-Security-Policy (CSP) Angular - 不要使用 unsafe-inline
- azure-devops-extensions - 自定义“新工作项”仪表板扩展
- python - 如何根据python中另一个列表的索引更改列表的值?
- asp.net-mvc - 在我的视图上使用数据注释时,电子邮件验证不起作用?
- python-3.x - Python 3中的列表索引超出范围
- java - @Bean 注解在 Spring Boot 中不起作用