Свойство зависимости - наследование от другого свойства? - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть собственное свойство зависимости в моем WPF UserControl с именем CustomForeground.

Я бы хотел, чтобы оно вернулось к UserControl.ForeGround, если в CustomForeground. * Значение не указано.1007 *

Я использую следующий код, который работает, но он определенно выглядит немного хакерским.

Может кто-нибудь подтвердить, есть ли «правильный» способ реализации этого свойства зависимости?

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

Примечание. Я пропустил декларацию для DependencyProperty, поскольку это всего лишь шаблон.

Ответы [ 3 ]

3 голосов
/ 11 апреля 2019

Вы можете добавить стиль в свой UserControl с помощью Setter для свойства CustomForeground, которое устанавливает привязку к свойству Foreground.

Привязка используется, если значение свойства CustomForeground не заменено другим Привязкой или локальным значением, анимацией и т. Д.

<UserControl ...>
    <UserControl.Style>
        <Style>
            <Setter
                Property="local:MyUserControl.CustomForeground"
                Value="{Binding Foreground, RelativeSource={RelativeSource Self}}"/>
        </Style>
    </UserControl.Style>
    ...
</UserControl>
0 голосов
/ 11 апреля 2019

Мне пришлось пойти на «восходящее» решение, а не «нисходящее», как @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>
0 голосов
/ 11 апреля 2019

Это должно сработать:

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 просто действует как своего рода прокси.

Когда затем установить MultiBinding из ForegroundProperty и CustomForegroundBackingProperty в CustomForegroundProperty.Для MultiBinding установлено значение TwoWay (поэтому любое изменение на CustomForegroundProperty запускает привязку, как и любое изменение ForegroundProperty или CustomForegroundBackingProperty).

Мы устанавливаем привязку CustomForegroundBackingProperty к TwoWay (как мы хотим, чтобы записи в CustomForegroundProperty влиялиCustomForegroundBackingProperty), но мы устанавливаем привязку ForegroundProperty к OneWay, поскольку мы не хотим, чтобы это произошло.

Затем мы помещаем конвертер в MultiBinding.Когда конвертер выполняет запись в CustomForegroundProperty, он просматривает как CustomForegroundBackingProperty, так и ForegroundProperty и выбирает ForegroundProperty, если CustomForegroundBackingProperty равен null.Это срабатывает, если изменяется либо ForegroundProperty, либо CustomForegroundBackingProperty.

Когда преобразователь пишет другим способом - т.е. пользователь пишет в CustomForegroundProperty - тогда мы просто возвращаем значение, которое они установили.Из-за режимов привязок в MultiBinding это означает, что для этого значения установлено значение CustomForegroundBackingProperty.

...