DependencyProperty 有时仅绑定,并在设计器中报告为缺失 属性

DependencyProperty only binds sometimes and is reported as a missing property in the designer

我对用户控件的依赖属性有一个非常奇怪的问题。

编译成功,但文本以预期方式出现。颜色 属性 适用于前 2 种用途(endColor 和 progressColor),但适用于文本的前景色。

即使它应该应用正确的颜色,endColor.Color 的值,它只是 returns 黑色 - 默认值。

虽然它编译并且应该工作,但设计者报告:"it can't find the property and marks my XAML as invalid"。

我已经重启VS并删除了设计器shadowcache,但没有用。

我主要是这样用的window:

<local:HoverButton x:Name="cancelButton" Text="Cancel" Color="Crimson" />

这是我的 xaml:

<UserControl x:Class="gbtis.HoverButton" x:Name="hoverButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:gbtis"
             mc:Ignorable="d">
    <Grid>
        <Border x:Name="borderBox" BorderThickness="4" CornerRadius="2">
            <Border.BorderBrush>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop x:Name="endColor" Color="{Binding Path=Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" Offset="0"/>

                    <GradientStop x:Name="progressColor" Color="{Binding Path=Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" Offset="1"/>
                    <GradientStop x:Name="progressBlack" Color="Black" Offset="1"/>

                    <GradientStop Color="Black" Offset="1"/>
                </LinearGradientBrush>
            </Border.BorderBrush>
            <Grid>
                <Viewbox>
                    <TextBlock x:Name="textBox"  Margin="2,0,2,0" 
                               Foreground="{Binding Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}"
                               Text="{Binding Text, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" />
                </Viewbox>
            </Grid>
        </Border>
    </Grid>
</UserControl>

还有我的控制代码:

    public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(HoverButton), new FrameworkPropertyMetadata(Colors.Black) { BindsTwoWayByDefault = true });
    public Color Color {
        get { return (Color)this.GetValue(ColorProperty); }
        set { SetValueDp(ColorProperty, value); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void SetValueDp(DependencyProperty property, object value,
        [System.Runtime.CompilerServices.CallerMemberName] String p = null) {
        SetValue(property, value);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
    }

更新:

我删除了我用来尝试强制更新的事件,并为文本框提供了纯色画笔。现在属性似乎起作用了。

但是...设计者仍然将它们显示为无法识别或无法访问

就像 clemens 所说的那样,依赖性 属性 不能那样工作。 您可以使用其 "PropertyChangedCallback".

public Color Color {
    get { return (Color)this.GetValue(ColorProperty); }
    set { SetValue(ColorProperty, value); }
}
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(HoverButton), new PropertyMetadata(Colors.Black, PropertyChanged));

public static void PropertyChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs e)
{
    //some code
}

但这只是需要的,如果你想在属性改变时做一些事情,不需要通知GUI。

顺便说一下,您的数据上下文应该是这样的:

public HoverButton()
{
    InitializeComponent();
    (this.Content as FrameworkElement).DataContext = this;
}

这样您的 CodeBehind 就可以绑定到 UserControl 并且 UserControl 从其父级继承 DataContext。

编辑:

Grx70 是对的。转换也不行。

http://blog.scottlogic.com/2010/07/09/a-universal-value-converter-for-wpf.html

指定的绑定不起作用的原因是因为您将类型为 BrushTextBlock.Foreground 属性 绑定到您的 HoverButton.Color 属性,属于 Color 类型,框架无法将 Color 转换为 Brush

因此,为了解决这个问题,您需要通过 Binding.Converter 属性 提供一个转换器来完成这项工作,或者提供一个刷子并使其使用 HoverButton.Color.在这种情况下,我认为您正在寻找的画笔是 SolidColorBrush:

<TextBlock (...)>
    <TextBlock.Foreground>
        <SolidColorBrush Color="{Binding Color, ElementName=hoverButton, UpdateSourceTrigger=PropertyChanged}" />
    </TextBlock.Foreground>
</TextBlock>

请注意,如果您采用第二种解决方案,那么进行绑定 TwoWay 几乎毫无意义。