【发布时间】:2018-04-04 10:26:38
【问题描述】:
我的视图模型中有一组变量:
public ObservableCollection<ObservableVariable> Variables { get; }= new ObservableCollection<ObservableVariable>();
ObservableVariable 类有两个属性:string Name 和 bool Selected;该类实现了 INotifyPropertyChanged,
我的目标是将此集合绑定到 WPF 视图中的清单,并使用 MultiBinding 将“全选”复选框绑定到该列表。下图说明了所需的视图。
观察下面的 XAML:
<CheckBox Content="Select All" Name="SelectAllCheckbox"></CheckBox>
...
<ListBox ItemsSource="{Binding Variables}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}">
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource LogicalOrConverter}" Mode="TwoWay">
<Binding Path="Selected"></Binding>
<Binding ElementName="SelectAllCheckbox" Path="IsChecked"></Binding>
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
LogicalOrConverter 接受任意数量的布尔值;如果有任何为真,则返回真。
正如您在上面看到的,每个复选框都绑定到视图模型中的一个变量以及“全选”复选框的状态。目前,除以下内容外,一切都按预期工作:如果我单击“全选”,则视图中的复选框会更新,但更改不会传播回视图模型。
请注意,我的实现中的大多数事情都可以正常工作。例如,如果我单击单个复选框,则视图模型会正确更新。
更详细的问题:
当我点击一个单独的复选框时,OnPropertyChanged 事件会在刚刚更改其框的变量中触发;转换器中的 ConvertBack 函数被触发;视图模型已更新,一切正常。
但是,当我单击“全选”复选框时,视图中的各个复选框都会更新,但不会在任何变量中调用 OnPropertyChanged,并且不会调用转换器中的 ConvertBack 函数。
另外,如果我取消选中“全选”,则各个检查将恢复到以前的状态。
更新视图模型的唯一方法是单击各个复选框。但是,多重绑定适用于视图。
我的问题是:
为什么对复选框的更改没有传播到视图模型中的源集合
转换器:
public class LogicalOrConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
foreach (object arg in values)
{
if ((arg is bool) && (bool)arg == true)
{
return true;
}
}
return false;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
object[] values = new object[2] {false, false};
if (value is bool && (bool) value == true)
values[0] = true;
return values;
}
}
ObservableVariable 定义:
public class ObservableVariable : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
private bool _selected;
public bool Selected
{
get { return _selected; }
set
{
_selected = value;
OnPropertyChanged(nameof(Selected));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
【问题讨论】:
-
一个问题 - 哪个值必须有复选框,如果它们是通过“全选”选择的,然后通过“全选”取消选择。使用您的 MValConverter,如果值将被传播到 VM,它们将永远不会被取消选择。
-
@Rekshino,抱歉回复晚了。我还没有弄清楚取消选择将如何工作。可能有必要为此添加逻辑,具体取决于我想要做什么。我故意忽略了这部分问题,因为我认为取消选择后勤是一个单独的问题。
-
如果您一定要使用多重绑定来更新视图模型,您可以通过解决方法获得它,但我怀疑它在实践中是否有用。如果您需要,我稍后会发布我的答案。
-
你需要吗?
-
@Rekshino 谢谢你的提议,但没有。我知道几种解决方法来解决我的问题以及如何实现它们。我在这里发布以了解我是否可以在真正的 MVVM 中实现这个全选复选框。对我来说,这意味着视图模型中没有全选逻辑,理想情况下,没有代码。
标签: c# wpf mvvm multibinding