WPF DependencyProperty ......现在它可以工作......现在它不会......为什么会这样?

时间:2011-01-29 01:29:50

标签: wpf callback dependency-properties

1 个答案:

答案 0 :(得分:0)

设置属性后,将不再应用样式。通过自己在已更改的处理程序中设置内部和外部画笔属性,依赖项属性子系统不会意识到更改实际上是由于样式而非显式执行。

一种解决方案是公开受保护的只读ActualInnerBorderBrushActualOuterBorderBrush属性,然后让所有三个用户可定义的属性在各自的更改处理程序中设置这些实际值。这样,用户可见的属性可以始终“由用户设置”而不会相互干扰。

修改

这是五个属性的完整工作实现:

public class Clock : StackPanel
{
    public Brush Brush
    {
        get { return (Brush)GetValue(BrushProperty); }
        set { SetValue(BrushProperty, value); }
    }

    public static readonly DependencyProperty BrushProperty =
        DependencyProperty.Register("Brush", typeof(Brush), typeof(Clock),
        new UIPropertyMetadata((d, e) => (d as Clock).OnBrushChanged(d, e)));

    public void OnBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ActualInnerBrush = e.NewValue as Brush;
        ActualOuterBrush = e.NewValue as Brush;
    }

    public Brush InnerBrush
    {
        get { return (Brush)GetValue(InnerBrushProperty); }
        set { SetValue(InnerBrushProperty, value); }
    }

    public static readonly DependencyProperty InnerBrushProperty =
        DependencyProperty.Register("InnerBrush", typeof(Brush), typeof(Clock),
        new UIPropertyMetadata((d, e) => (d as Clock).OnInnerBrushChanged(d, e)));

    public void OnInnerBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ActualInnerBrush = e.NewValue as Brush;
    }

    public Brush OuterBrush
    {
        get { return (Brush)GetValue(OuterBrushProperty); }
        set { SetValue(OuterBrushProperty, value); }
    }

    public static readonly DependencyProperty OuterBrushProperty =
        DependencyProperty.Register("OuterBrush", typeof(Brush), typeof(Clock),
        new UIPropertyMetadata((d, e) => (d as Clock).OnOuterBrushChanged(d, e)));

    public void OnOuterBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ActualOuterBrush = e.NewValue as Brush;
    }

    public Brush ActualInnerBrush
    {
        get { return (Brush)GetValue(ActualInnerBrushProperty); }
        private set { SetValue(ActualInnerBrushPropertyKey, value); }
    }

    private static readonly DependencyPropertyKey ActualInnerBrushPropertyKey =
        DependencyProperty.RegisterReadOnly("ActualInnerBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata());
    public static readonly DependencyProperty ActualInnerBrushProperty = ActualInnerBrushPropertyKey.DependencyProperty;


    public Brush ActualOuterBrush
    {
        get { return (Brush)GetValue(ActualOuterBrushProperty); }
        private set { SetValue(ActualOuterBrushPropertyKey, value); }
    }

    private static readonly DependencyPropertyKey ActualOuterBrushPropertyKey =
        DependencyProperty.RegisterReadOnly("ActualOuterBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata());
    public static readonly DependencyProperty ActualOuterBrushProperty = ActualOuterBrushPropertyKey.DependencyProperty;
}

这是一个小测试程序来证明它有效:

<Grid>
    <Grid.Resources>
        <Style x:Key="styleBrush" TargetType="local:Clock">
            <Setter Property="Brush" Value="Red"/>
        </Style>
        <Style x:Key="styleInnerOnly" TargetType="local:Clock">
            <Setter Property="InnerBrush" Value="Green"/>
        </Style>
        <Style x:Key="styleInnerOuter" TargetType="local:Clock">
            <Setter Property="InnerBrush" Value="Blue"/>
            <Setter Property="OuterBrush" Value="Yellow"/>
        </Style>
        <Style x:Key="styleEmpty" TargetType="local:Clock"/>
    </Grid.Resources>
    <StackPanel>
        <local:Clock x:Name="clock" Orientation="Horizontal">
            <Rectangle Width="100" Height="100" Fill="{Binding ActualInnerBrush, ElementName=clock}"/>
            <Rectangle Width="100" Height="100" Fill="{Binding ActualOuterBrush, ElementName=clock}"/>
        </local:Clock>
        <StackPanel Orientation="Horizontal">
            <Button Content="Default">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{x:Null}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
            <Button Content="BrushOnly">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleBrush}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
            <Button Content="InnerOnly">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleInnerOnly}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
            <Button Content="InnerOuter">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleInnerOuter}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
            <Button Content="Empty">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleEmpty}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
        </StackPanel>
    </StackPanel>
</Grid>

此示例使用行为。如果您不熟悉行为,请安装Expression Blend 4 SDK并添加以下命名空间:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

并将System.Windows.InteractivityMicrosoft.Expression.Interactions添加到您的项目中。