WPF从属属性。。。现在它工作了。。。现在它不';T怎么会?

WPF从属属性。。。现在它工作了。。。现在它不';T怎么会?,wpf,callback,dependency-properties,Wpf,Callback,Dependency Properties,我有一个ClockFace UserControl,它公开了许多属性,使用户能够对其进行样式设置。时钟有两个椭圆物体作为边界;外部边界和内部边界 <Ellipse Name="OuterBorder" Panel.ZIndex="5" StrokeThickness="{Binding BorderOuterThickness}" Stroke="{Binding BorderOuteBrush}" /> <Ellipse Name="InnerBorder" Panel.ZI

我有一个ClockFace UserControl,它公开了许多属性,使用户能够对其进行样式设置。时钟有两个椭圆物体作为边界;外部边界和内部边界

<Ellipse Name="OuterBorder" Panel.ZIndex="5" StrokeThickness="{Binding BorderOuterThickness}" Stroke="{Binding BorderOuteBrush}" />
<Ellipse Name="InnerBorder" Panel.ZIndex="6" StrokeThickness="{Binding BorderInnerThickness}" Margin="{Binding StrokeThickness, ElementName=OuterBorder}" Stroke="{Binding BorderInnerBrush}">

public static readonly DependencyProperty BorderInnerBrushProperty = DependencyProperty.Register("BorderInnerBrush", typeof(Brush), typeof(ClockFace), new 

PropertyMetadata(new LinearGradientBrush(Color.FromRgb(118, 57, 57), Color.FromRgb(226, 185, 185), new Point(0.5, 0), new Point(0.5, 1))));

public Brush BorderInnerBrush
{
    get { return (Brush)GetValue(BorderInnerBrushProperty); }
    set { SetValue(BorderInnerBrushProperty, value); }
}

public static readonly DependencyProperty BorderOuterBrushProperty = DependencyProperty.Register("BorderOuterBrush", typeof(Brush), typeof(ClockFace), new 

PropertyMetadata(new LinearGradientBrush(Color.FromRgb(226, 185, 185), Color.FromRgb(118, 57, 57), new Point(0.5, 0), new Point(0.5, 1))));

public Brush BorderOuterBrush
{
    get { return (Brush)GetValue(BorderOuterBrushProperty); }
    set { SetValue(BorderOuterBrushProperty, value); }
}
当在样式中设置BorderBrush属性时,一切正常。。。直到我在运行时切换样式。现在最奇怪的事情发生了。。。让我解释一下

我有四种预设的风格,每种都很好用。其中三个使用两个BorderInnerBrush和BorderOuterBrush属性,一个使用快捷方式BorderBrush属性。我可以使用ContextMenu和一些代码在样式之间切换,这些代码从资源中访问xaml样式,并将它们设置为ClockFace对象的Style属性

我可以无休止地在三种不使用快捷方式属性的样式之间切换。我也可以切换到使用快捷方式属性的样式,它看起来很好。这就是奇怪的开始

切换到使用BorderBrush特性的样式后,BorderInnerBrush和BorderOuterBrush特性将停止工作。在各种样式中设置的预设笔刷对象不再在两个椭圆对象上设置。我将一些PropertyChangedCallback方法插入到内部和外部边界属性中,以查看发生了什么

当我第一次运行应用程序时,我可以毫无问题地切换到不使用快捷方式属性的三种样式。我在所有三个边界笔刷属性的PropertyChangedCallback方法上设置了断点,并调试了程序。当切换到这三种样式中的每一种时,内部和外部边界属性的“回调方法”断点都会像您所期望的那样被命中。切换到使用BorderBrush属性的样式时,其回调方法的断点被命中。SetbOrderBrush方法设置另外两个边界笔刷对象,以便按照预期命中内部和外部边界属性“回调方法”断点

同样,这是奇怪的部分。在此之后切换到其他三种样式中的任何一种时,内部和外部边界属性的“回调方法”断点将不再命中。相反,当e.NewValue的值为null时,会命中连接到BorderBrush属性的回调方法中的断点。由于SetbOrderBrusks方法中忽略了null值,因此不会再遇到断点

经过进一步调查,我发现e.NewValue为null,因为BorderBrushProperty DependencyProperty上没有设置默认值。事实上,在向声明中添加默认笔刷对象之后,这就是将在回调方法中的e.NewValue中传递的笔刷。尽管两个内部和外部边界属性的回调方法中的断点在此之后会被命中,但这只是因为它们是在setbOrderBrush方法中设置的。样式中的BorderInnerBrush和BorderOuterBrush对象中设置的笔刷对象在BorderBrush属性使用一次后将永远不会传递给这些属性

最后需要注意的一点是,正如在样式中未显式设置值时设置BorderBrushProperty属性的默认值一样,在样式中未显式设置值时,也会设置内部和外部border DependencyProperty对象的默认值,但仅当样式中未设置BorderBrush特性时

我已经被困在这个问题上好几天了,虽然一个简单的解决办法是删除快捷方式属性,但我宁愿找出发生了什么并修复它。我希望我已经提供了足够的信息让bright spark能够解决这个问题,所以,如果你有任何想法或问题,请分享。非常感谢

更新>>

根据Rick的建议,我创建了另一对笔刷属性,并通过附加到其他三个笔刷属性的回调方法设置它们。使用此设置,我可以在所有样式之间切换,而不会出现任何视觉问题。。。至少我是这么想的

现在,我可以从使用BorderBrush(快捷方式)属性的样式切换到设置两个BorderInner和BorderOuter属性的样式,并正确更新边框,因此感谢Rick让我更进一步。从设置BorderBrush属性的样式切换到不显式设置任何边界笔刷的样式时,仍然存在问题

因此,我仍然有一个相同的问题,即BorderInnerBrush和BorderOuterBrush属性在从代码隐藏设置后不能直接工作。新的是,如果我切换到设置两个笔刷属性的样式,这似乎会再次“唤醒它们”。。。如果然后切换到不设置边框笔刷的样式,则内部和外部特性将再次正确设置其默认值

只有在使用样式设置了两个边界属性(从“代码隐藏”到“样式设置”或使用其默认值)之后,它们才会失效。这太奇怪了。。。有人能解决吗

更新2>>>

首先,非常感谢您的时间和示例。在将Rick的示例代码复制并粘贴到一个新项目中之后,我不得不在它运行之前做一些修改。。。也许是因为我没有表达式混合4?我安装了SDK并将引用添加到了注意到的DLL,但不得不使用以下XML名称空间声明:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
我还必须将每个ChangePropertyAction声明稍微更改为:

<ei:ChangePropertyAction TargetName="clock" PropertyName="Style" Value="{StaticResource styleBrush}"/>
现在这个项目有一个类似的问题。。。默认值永远不会重置。我对这种行为感到莫名其妙

我已经在这个问题上花了很长时间,虽然我从Rick那里学到了很多有用的东西,但我仍然存在默认值的问题。我决定最简单的方法是删除快捷方式BorderBrush属性。瑞克帮了很多忙
<ei:ChangePropertyAction TargetName="clock" PropertyName="Style" Value="{StaticResource styleBrush}"/>
private static readonly DependencyPropertyKey ActualInnerBrushPropertyKey = DependencyProperty.RegisterReadOnly("ActualInnerBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata(Brushes.Teal));

private static readonly DependencyPropertyKey ActualOuterBrushPropertyKey = DependencyProperty.RegisterReadOnly("ActualOuterBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata(Brushes.Salmon));
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>
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"