自定义依赖项属性不会更新源

时间:2018-11-15 01:30:21

标签: c# wpf custom-controls dependency-properties

我正在创建一个自定义控件,我想添加一个与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中所做的更改才会触发设置程序。因此,事件触发器肯定是在修改依赖项属性,因为(a)调用了属性已更改的回调,并且(b)IntegerUpDown(绑定到依赖项属性)中的值已更新。

我在这里想念什么?

0 个答案:

没有答案