我在WPF UserControl
中有一个名为CustomForeground
的自定义依赖项属性。
如果未在UserControl.ForeGround
上指定任何值,我希望它回退到CustomForeground
。
我正在使用下面的代码,该代码可以正常工作,但是肯定有点黑。
任何人都可以确认确认是否存在实现此依赖项属性的“正确”方法吗?
public SolidColorBrush CustomForeground
{
get { return (SolidColorBrush)(GetValue(CustomForegroundProperty) ?? GetValue(ForegroundProperty)); }
set { SetValue(CustomForegroundProperty, value); }
}
注意-我省略了DependencyProperty
的声明,因为它只是样板。
答案 0 :(得分:3)
您可以使用Setter为CustomForeground属性向用户控件添加样式,该属性将Binding设置为其Foreground属性。
除非使用其他绑定或本地值或动画等替换CustomForeground属性值,否则将使用Binding。
<UserControl ...>
<UserControl.Style>
<Style>
<Setter
Property="local:MyUserControl.CustomForeground"
Value="{Binding Foreground, RelativeSource={RelativeSource Self}}"/>
</Style>
</UserControl.Style>
...
</UserControl>
答案 1 :(得分:0)
这应该可以解决问题:
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
var multiBinding = new MultiBinding()
{
Converter = FallbackColorConverter.Instance,
Mode = BindingMode.TwoWay,
Bindings =
{
new Binding()
{
Source = this,
Path = new PropertyPath(CustomForegroundBackingProperty),
Mode = BindingMode.TwoWay
},
new Binding()
{
Source = this,
Path = new PropertyPath(ForegroundProperty),
Mode = BindingMode.OneWay
},
},
};
SetBinding(CustomForegroundProperty, multiBinding);
}
public Brush CustomForeground
{
get => (Brush)GetValue(CustomForegroundProperty);
set => SetValue(CustomForegroundProperty, value);
}
public static readonly DependencyProperty CustomForegroundProperty =
DependencyProperty.Register(nameof(CustomForeground), typeof(Brush), typeof(MyControl), new PropertyMetadata(null));
private static readonly DependencyProperty CustomForegroundBackingProperty =
DependencyProperty.Register("CustomForegroundBacking", typeof(Brush), typeof(MyControl), new PropertyMetadata(null));
private class FallbackColorConverter : IMultiValueConverter
{
public static readonly FallbackColorConverter Instance = new FallbackColorConverter();
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values[0] ?? values[1];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return new object[] { value };
}
}
}
我们设置了两个DependencyProperties。 CustomForegroundBackingProperty充当用户设置的任何CustomForeground值的实际存储。 CustomForegroundProperty只是一种代理。
然后在那时设置从ForegroundProperty和CustomForegroundBackingProperty到CustomForegroundProperty的MultiBinding。 MultiBinding设置为TwoWay(因此,对CustomForegroundProperty进行的任何更改都会触发绑定,对ForegroundProperty或CustomForegroundBackingProperty的任何更改也会触发绑定。)
我们将到CustomForegroundBackingProperty的绑定设置为TwoWay(因为我们要写入CustomForegroundProperty来影响CustomForegroundBackingProperty),但是我们不希望将到ForegroundProperty的绑定设置为OneWay。
然后我们在MultiBinding上放置一个转换器。当转换器写入CustomForegroundProperty时,它将同时查看CustomForegroundBackingProperty和ForegroundProperty,如果CustomForegroundBackingProperty为null
,则选择ForegroundProperty。如果ForegroundProperty或CustomForegroundBackingProperty发生更改,则会触发此事件。
当转换器以另一种方式写(即用户写到CustomForegroundProperty)时,我们只返回他们设置的值。由于MultiBinding中绑定的模式,这意味着此值将设置为CustomForegroundBackingProperty。
答案 2 :(得分:0)
我不得不采用“自下而上”的解决方案,而不是像@Clemens这样的“自上而下”的解决方案(因为我已经在UserControl
上定义了样式。它看起来像这样:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{Binding ValueBrush}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ValueBrush}" Value="{x:Null}">
<Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>