双向多重绑定 [英] TwoWay MultiBinding
问题描述
玩MultiBinding
:
我想要的是:单击任一复选框应切换所有其他复选框.
What I want: clicking either checkbox should toggle all others.
问题:单击A
不会更改B
,单击B
不会更改A
. Result
有效.
Problem: clicking A
doesn't change B
, clicking B
doesn't change A
. Result
works.
问题:在仍使用MultiBinding
的情况下如何解决?
Question: how would I fix it, while still using MultiBinding
?
PS:这是试图解决更复杂的问题的尝试,在提供将所有复选框绑定到一个属性.
P.S.: this is an attempt to solve more complicated problem, please refer to it before offering to bind all checkboxes to a single property.
下面是一个 mcve .
xaml:
<StackPanel>
<CheckBox Content="A" IsChecked="{Binding A}" />
<CheckBox Content="B" IsChecked="{Binding B}" />
<CheckBox Content="Result">
<CheckBox.IsChecked>
<MultiBinding Converter="{local:MultiBindingConverter}">
<Binding Path="A" />
<Binding Path="B" />
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</StackPanel>
cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
ViewModel:
ViewModel:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string property = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
bool _a;
public bool A
{
get { return _a; }
set { _a = value; OnPropertyChanged(); }
}
bool _b;
public bool B
{
get { return _b; }
set { _b = value; OnPropertyChanged(); }
}
}
转换器:
public class MultiBindingConverter : MarkupExtension, IMultiValueConverter
{
public MultiBindingConverter() { }
public override object ProvideValue(IServiceProvider serviceProvider) => this;
object[] _old;
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
// first time init
if (_old == null)
_old = values.ToArray();
// find if any value is changed and return value
for (int i = 0; i < values.Length; i++)
if (values[i] != _old[i])
{
_old = values.ToArray();
return values[i];
}
// if no changes return first value
return values[0];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
Enumerable.Repeat(value, targetTypes.Length).ToArray();
}
推荐答案
简单的原因是,当您单击CheckBox
A 时,将永远不会调用ConvertBack()
方法.
The simple reason is, the ConvertBack()
method will never be called when you click CheckBox
A.
请考虑以下原因:
Checkbox
A 得到检查.
<Binding />
调用Property-Setter A .
<Binding />
calls Property-Setter A.
资产设定者 A 被呼叫.
财产设定者 A 呼叫OnPropertyChanged("A")
.
PropertyChanged-Event由CheckBox
结果的<MultiBinding />
接收.
PropertyChanged-Event is recieved by the <MultiBinding />
of CheckBox
Result.
属性键 A 和 B .
MultiBindingConverter.Convert()
方法.
<MultiBinding />
更新视图中的CheckBox
结果 IsChecked
状态.
<MultiBinding />
updates the CheckBox
Result IsChecked
state in the view.
无需触摸CheckBox
B并仅调用属性 B 的获取方法即可完成更改.
Handling of change is done without ever touching CheckBox
B and only calling the getter of property B.
如果所有CheckBox
上都有一个MultiBinding
,则将调用所有适当的设置器.但是,如果每个CheckBox
的更改行为都不同,则可能需要实现一个不同的Converter.
If you have a MultiBinding
on all CheckBox
es, then all appropriate setters will be called. You might need to implement a different Converter though, if the change behaviour should be different for each CheckBox
.
这也是原因,如果可能的话,最好在ViewModel中最好进行这样的更改,因为所有这些Bindings和Converters使得跟踪变得有些困难.
That is also the reason, why changing stuff like that should - preferably - be done within the ViewModel if possible, because all those Bindings and Converters make it a little hard to track.
这篇关于双向多重绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!