依赖属性 - 从另一个属性继承?

问题描述 投票:0回答:3

我在我的WPF UserControl中有一个名为CustomForeground的自定义依赖项属性。

如果没有在UserControl.ForeGround上指定值,我希望它回退到CustomForeground

我正在使用以下代码,它可以工作,但它确实感觉有点hacky。

任何人都可以确认是否有一种“正确”的方式来实现这种依赖属性?

public SolidColorBrush CustomForeground
{
      get { return (SolidColorBrush)(GetValue(CustomForegroundProperty) ?? GetValue(ForegroundProperty)); }
      set { SetValue(CustomForegroundProperty, value); }
}

注意 - 我遗漏了DependencyProperty的声明,因为它只是样板。

c# wpf dependency-properties
3个回答
3
投票

您可以使用自定义前景属性的Setter向用户控件添加样式,该属性将Binding设置为其Foreground属性。

除非CustomForeground属性值被另一个Binding或本地值或动画等替换,否则将使用Binding。

<UserControl ...>
    <UserControl.Style>
        <Style>
            <Setter
                Property="local:MyUserControl.CustomForeground"
                Value="{Binding Foreground, RelativeSource={RelativeSource Self}}"/>
        </Style>
    </UserControl.Style>
    ...
</UserControl>

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中的MultiBinding设置为CustomForegroundProperty。 MultiBinding设置为TwoWay(因此更改对CustomForegroundProperty的任何更改都会触发绑定,对ForegroundProperty或CustomForegroundBackingProperty的任何更改也是如此)。

我们将对CustomForegroundBackingProperty的绑定设置为TwoWay(因为我们希望写入CustomForegroundProperty以影响CustomForegroundBackingProperty),但我们将ForegroundProperty的绑定设置为OneWay,因为我们不希望这种情况发生。

然后我们在MultiBinding上放置一个转换器。当转换器写入CustomForegroundProperty时,它会查看CustomForegroundBackingProperty和ForegroundProperty,如果CustomForegroundBackingProperty是null,则选择ForegroundProperty。如果ForegroundProperty或CustomForegroundBackingProperty更改,则会触发此操作。

当转换器以另一种方式写入时 - 即用户写入CustomForegroundProperty - 然后我们只返回它们设置的值。由于MultiBinding中绑定的模式,这意味着此值设置为CustomForegroundBackingProperty。


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>
© www.soinside.com 2019 - 2024. All rights reserved.