通过MarkupExtension抛出IsChecked的WPF ToggleButton多绑定



我正试图通过解析为MultiBinding的标记扩展绑定ToggleButtonIsChecked属性。在XAML中,我有两个源切换按钮和一个目标切换按钮,它的IsChecked应该绑定到源按钮的IsChecked

<ToggleButton x:Name="Source1" Content="Source 1" Margin="5" Padding="5,2"/>
<ToggleButton x:Name="Source2" Content="Source 2" Margin="5" Padding="5,2"/>
<ToggleButton Content="Target" Margin="5" Padding="5,2">
<ToggleButton.IsChecked>
<local:ExMultiBinding  Converter="{StaticResource AnyConverter}">
<Binding ElementName="Source1" Path="IsChecked"/>
<Binding ElementName="Source2" Path="IsChecked"/>
</local:ExMultiBinding>
</ToggleButton.IsChecked>
</ToggleButton>

我提供MultiBinding的标记扩展看起来像这个

[ContentProperty("Bindings")]
public class ExMultiBindingExtension : MarkupExtension, INotifyPropertyChanged
{
public Collection<BindingBase> Bindings { get; set; } = new Collection<BindingBase>();
public IMultiValueConverter Converter { get; set; }
public BindingMode Mode { get; set; }
public UpdateSourceTrigger UpdateSourceTrigger { get; set; }

public override object ProvideValue(IServiceProvider serviceProvider)
{
var multi = new MultiBinding
{
Converter = Converter,
Mode = Mode,
UpdateSourceTrigger = UpdateSourceTrigger
};
return multi;
}
public event PropertyChangedEventHandler PropertyChanged;
}

启动UI会产生

ArgumentException: 'System.Windows.Data.MultiBinding' is not a valid value for property 'IsChecked'.

我检查了一下,ToggleButton实现上的IsChecked属性实际上没有标记

[Bindable(true)]

但仅使用

[Category("Appearance")]
[TypeConverter(typeof (NullableBoolConverter))]
[Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]

通过XAML中的BindingMultiBinding进行直接绑定是可行的。

示例代码经过简化以突出问题。由于实现更加复杂,因此不可能在实际代码中避免MarkupExtension。

BindingBase本身就是一个MarkupExtension。当然,markupExtension不是bool类型,不能分配给bool类型的成员。

调用扩展的原因是XAML解析器想要解析每个MarkupExtension。这是通过调用MarkupExtension.ProvideValue方法来完成的。在这种情况下,BindingBase对象将与BindingExpressionBase对象相关联。此BindingExpressionBase将解析底层绑定以返回实际值(简化(。

因此,您必须手动解析BindingBase标记:

public override object ProvideValue(IServiceProvider serviceProvider)
{
var multi = new MultiBinding
{
Converter = Converter,
Mode = Mode,
UpdateSourceTrigger = UpdateSourceTrigger
};
// Resolve the MarkupExtension BindingBase
return multi.ProvideValue(serviceProvider);
}

最新更新