有没有更简单的方法来更新 WPF 中的相关属性?

Is there an easier way to update related properties in WPF?

我有一个 UserControl,它将评级显示为星数。它通过将 TextBlock 的文本 属性 绑定到常规代码隐藏 属性 来实现,后者又使用整数 DependencyProperty Value.

为了在 Value 更改时更新 TextBlock,我需要从 DependencyProperty 的 PropertyChangedCallback 手动触发 INotifyPropertyChanged.PropertyChanged 事件。

这感觉太过分了。有没有更简单的方法来完成这个?

<TextBlock Text="{Binding RatingDisplay, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Rating}}}" />
public partial class Rating : UserControl, INotifyPropertyChanged
{
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(int), typeof(Rating), new PropertyMetadata(0, (sender, e) =>
        {
            ((Rating)sender).RaisePropertyChanged(nameof(RatingDisplay));
        }));

    public Rating()
    {
        InitializeComponent();
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    public int Value
    {
        get => (int)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    public string RatingDisplay => new string('*', Value);

    protected void RaisePropertyChanged(string? propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

您不需要在公开依赖属性的 class 中实现 INotifyPropertyChanged。依赖属性提供自己的更改通知机制。

为了更新只读依赖项 属性,像这样的东西应该可以工作:

public partial class Rating : UserControl
{
    private static readonly DependencyPropertyKey RatingDisplayPropertyKey =
        DependencyProperty.RegisterReadOnly(
            nameof(RatingDisplay), typeof(string), typeof(Rating), null);

    public static readonly DependencyProperty RatingDisplayProperty =
        RatingDisplayPropertyKey.DependencyProperty;

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register(
            nameof(Value), typeof(int), typeof(Rating),
            new PropertyMetadata(0, (o, e) => o.SetValue(
                RatingDisplayPropertyKey, new string('*', (int)e.NewValue))));

    public Rating()
    {
        InitializeComponent();
    }

    public int Value
    {
        get => (int)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    public string RatingDisplay => (string)GetValue(RatingDisplayProperty);
}

或者,将值 属性 与从评分值创建字符串的绑定转换器绑定。


或者,可能是最简单的,直接访问应该更新的 UI 元素:

<TextBlock x:Name="ratingDisplay"/>

后面有这段代码:

public partial class Rating : UserControl
{
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register(
            nameof(Value), typeof(int), typeof(Rating),
            new PropertyMetadata(0, (o, e) =>
                ((Rating)o).ratingDisplay.Text = new string('*', (int)e.NewValue)));

    public Rating()
    {
        InitializeComponent();
    }

    public int Value
    {
        get => (int)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }
}