Пользовательское свойство зависимости не будет обновлять источник - PullRequest
0 голосов
/ 15 ноября 2018

Я создаю пользовательский элемент управления и хочу добавить свойство зависимостей, которое работает как CheckBox.IsChecked, т. Е. Когда пользователь щелкает элемент управления, привязка обновляет источник.Объявление для этого пользовательского элемента управления выглядит следующим образом:

public class QuadStateSelector : Control
{
    static QuadStateSelector()
    {
        PropertyChangedCallback callback = new PropertyChangedCallback(OnValueChanged);
        FrameworkPropertyMetadata md = new FrameworkPropertyMetadata(0, callback);
        md.BindsTwoWayByDefault = true;
        md.DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged;
        ValueProperty = DependencyProperty.Register(nameof(Value), typeof(int), typeof(QuadStateSelector), md);

        DefaultStyleKeyProperty.OverrideMetadata(typeof(QuadStateSelector), new FrameworkPropertyMetadata(typeof(QuadStateSelector)));
    }

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    }

    public int Value
    {
        get { return (int)this.GetValue(ValueProperty); }
        set { this.SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty;

Как вы можете видеть, привязка по умолчанию - 2-сторонняя, инициируемая при изменении источника.Я также добавил обратный вызов, чтобы я мог видеть, когда свойство изменяется.

Мой XAML:

<rt:QuadStateSelector Name="qss" Value="{Binding LineState}" Canvas.Left="262" Canvas.Top="10" Background="Azure"/>
<xctk:IntegerUpDown Value="{Binding ElementName=qss, Path=Value }"/>

И мой источник:

public int LineState
{
    get => _LineState;
    set => _LineState = value;    // This line is never called
}

Изменения в значении свойства зависимостей производятся с помощью триггеров событий в шаблоне элемента управления, как показано ниже:

<Style TargetType="{x:Type local:QuadStateSelector}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:QuadStateSelector}">
                <StackPanel Orientation="Horizontal" Background="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}">
                    <Ellipse Margin="1,0,1,0" Name="Button1" Width="14" Height="14" Stroke="{Binding Button1Brush, RelativeSource={RelativeSource TemplatedParent}}" StrokeThickness="2" Fill="AntiqueWhite"/>
                    <Ellipse Margin="1,0,1,0" Name="Button2" Width="14" Height="14" Stroke="{Binding Button2Brush, RelativeSource={RelativeSource TemplatedParent}}" StrokeThickness="2" Fill="AntiqueWhite"/>
                    <Ellipse Margin="1,0,1,0" Name="Button3" Width="14" Height="14" Stroke="{Binding Button3Brush, RelativeSource={RelativeSource TemplatedParent}}" StrokeThickness="2" Fill="AntiqueWhite"/>
                    <Ellipse Margin="1,0,1,0" Name="Button4" Width="14" Height="14" Stroke="{Binding Button4Brush, RelativeSource={RelativeSource TemplatedParent}}" StrokeThickness="2" Fill="AntiqueWhite"/>
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="Value" Value="0">
                        <Setter TargetName="Button1" Property="Fill" Value="{Binding Button1Brush, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="Value" Value="1">
                        <Setter TargetName="Button2" Property="Fill" Value="{Binding Button2Brush, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="Value" Value="2">
                        <Setter TargetName="Button3" Property="Fill" Value="{Binding Button3Brush, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="Value" Value="3">
                        <Setter TargetName="Button4" Property="Fill" Value="{Binding Button4Brush, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Trigger>
                    <EventTrigger RoutedEvent="Control.MouseDown" SourceName="Button1">
                        <BeginStoryboard>
                            <Storyboard>
                                <Int32AnimationUsingKeyFrames Storyboard.TargetProperty="Value" Duration="0:0:1">
                                    <DiscreteInt32KeyFrame KeyTime="0" Value="0"/>
                                </Int32AnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Control.MouseDown" SourceName="Button2">
                        <BeginStoryboard>
                            <Storyboard>
                                <Int32AnimationUsingKeyFrames Storyboard.TargetProperty="Value" Duration="0:0:1">
                                    <DiscreteInt32KeyFrame KeyTime="0" Value="1"/>
                                </Int32AnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Control.MouseDown" SourceName="Button3">
                        <BeginStoryboard>
                            <Storyboard>
                                <Int32AnimationUsingKeyFrames Storyboard.TargetProperty="Value" Duration="0:0:1">
                                    <DiscreteInt32KeyFrame KeyTime="0" Value="2"/>
                                </Int32AnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Control.MouseDown" SourceName="Button4">
                        <BeginStoryboard>
                            <Storyboard>
                                <Int32AnimationUsingKeyFrames Storyboard.TargetProperty="Value" Duration="0:0:1">
                                    <DiscreteInt32KeyFrame KeyTime="0" Value="3"/>
                                </Int32AnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Существует два взаимосвязанных элемента управления, и когда я запускаю приложение, изменения в одном элементе управления отражаются вдругие, но только изменения, сделанные в IntegerUpDown, приводят к срабатыванию установщика.Таким образом, триггеры событий определенно изменяют свойство зависимости, потому что (а) вызывается обратный вызов измененного свойства, и (б) значение в IntegerUpDown (привязанное к свойству зависимости) обновляется.

Что мне здесь не хватает?

...