c# – 为什么我的WPF CheckBox绑定不起作用?
我正在使用MVVM,VS 2008和.NET 3.5 SP1.我有一个项目列表,每个项目都暴露一个IsSelected属性.我添加了一个CheckBox来管理列表中所有项目的选择/取消选择(更新每个项目的IsSelected属性).一切正常,但是当PropertyChanged事件触发CheckBox的绑定控件时,视图中没有更新IsChecked属性.
<CheckBox Command="{Binding SelectAllCommand}" IsChecked="{Binding Path=AreAllSelected,Mode=OneWay}" Content="Select/deselect all identified duplicates" IsThreeState="True" /> 我的VM: public class MainViewModel : BaseViewModel { public MainViewModel(ListViewModel listVM) { ListVM = listVM; ListVM.PropertyChanged += OnListVmChanged; } public ListViewModel ListVM { get; private set; } public ICommand SelectAllCommand { get { return ListVM.SelectAllCommand; } } public bool? AreAllSelected { get { if (ListVM == null) return false; return ListVM.AreAllSelected; } } private void OnListVmChanged(object sender,PropertyChangedEventArgs e) { if (e.PropertyName == "AreAllSelected") OnPropertyChanged("AreAllSelected"); } } 我没有在这里显示SelectAllCommand或单个项目选择的实现,但它似乎没有相关性.当用户选择列表中的单个项目(或单击问题CheckBox来选择/取消选择所有项目)时,我已经验证了OnPropertyChanged(“AreAllSelected”)代码行的执行,以及在调试器中的跟踪,可以看到PropertyChanged事件已订阅并按预期触发.但AreAllSelected属性的get只执行一次 – 实际呈现视图时. Visual Studio的“输出”窗口不报告任何数据绑定错误,因此从我可以看出,CheckBox的IsSelected属性已正确绑定. 如果我用Button替换CheckBox: <Button Content="{Binding SelectAllText}" Command="{Binding SelectAllCommand}"/> 并更新VM: ... public string SelectAllText { get { var msg = "Select All"; if (ListVM != null && ListVM.AreAllSelected != null && ListVM.AreAllSelected.Value) msg = "Deselect All"; return msg; } } ... private void OnListVmChanged(object sender,PropertyChangedEventArgs e) { if (e.PropertyName == "AreAllSelected") OnPropertyChanged("SelectAllText"); } 一切都按预期工作 – 按钮的文本会更新,因为所有项目都被选中/取消.在CheckBox的IsSelected属性上有关于绑定的东西吗? 谢谢你的帮助! 解决方法
我发现了问题.似乎在WPF 3.0中存在一个错误,在IsChecked上使用OneWay绑定导致绑定被删除.感谢
this post的帮助,听起来像是在WPF 4.0中修复了这个bug
要重现,请创建一个新的WPF项目. 添加FooViewModel.cs: using System; using System.ComponentModel; using System.Windows.Input; namespace Foo { public class FooViewModel : INotifyPropertyChanged { private bool? _isCheckedState = true; public FooViewModel() { ChangeStateCommand = new MyCmd(ChangeState); } public bool? IsCheckedState { get { return _isCheckedState; } } public ICommand ChangeStateCommand { get; private set; } private void ChangeState() { switch (_isCheckedState) { case null: _isCheckedState = true; break; default: _isCheckedState = null; break; } OnPropertyChanged("IsCheckedState"); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { var changed = PropertyChanged; if (changed != null) changed(this,new PropertyChangedEventArgs(propertyName)); } } public class MyCmd : ICommand { private readonly Action _execute; public event EventHandler CanExecuteChanged; public MyCmd(Action execute) { _execute = execute; } public void Execute(object parameter) { _execute(); } public bool CanExecute(object parameter) { return true; } } } 修改Window1.xaml.cs: using System.Windows; using System.Windows.Controls.Primitives; namespace Foo { public partial class Window1 { public Window1() { InitializeComponent(); } private void OnClick(object sender,RoutedEventArgs e) { var bindingExpression = MyCheckBox.GetBindingExpression(ToggleButton.IsCheckedProperty); if (bindingExpression == null) MessageBox.Show("IsChecked property is not bound!"); } } } 修改Window1.xaml: <Window x:Class="Foo.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:Foo" Title="Window1" Height="200" Width="200" > <Window.DataContext> <vm:FooViewModel /> </Window.DataContext> <StackPanel> <CheckBox x:Name="MyCheckBox" Command="{Binding ChangeStateCommand}" IsChecked="{Binding Path=IsCheckedState,Mode=OneWay}" Content="Foo" IsThreeState="True" Click="OnClick"/> <Button Command="{Binding ChangeStateCommand}" Click="OnClick" Content="Change State"/> </StackPanel> </Window> 单击按钮几次,看到CheckBox的状态在true和null之间切换(非假).但是单击CheckBox,您将看到Binding已从IsChecked属性中删除. 解决方法: 将IsChecked绑定更新为TwoWay并将其UpdateSourceTrigger设置为显式: IsChecked="{Binding Path=IsCheckedState,Mode=TwoWay,UpdateSourceTrigger=Explicit}" 并更新绑定属性,使其不再是只读的: public bool? IsCheckedState { get { return _isCheckedState; } set { } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |