有没有更简单的方法来更新 WPF 中的相关属性?
Posted
技术标签:
【中文标题】有没有更简单的方法来更新 WPF 中的相关属性?【英文标题】:Is there an easier way to update related properties in WPF? 【发布时间】:2021-11-08 16:03:45 【问题描述】:我有一个将评分显示为星数的 UserControl。它通过将 TextBlock 的 Text 属性绑定到常规代码隐藏属性来实现此目的,该属性又使用整数 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));
【问题讨论】:
为什么不使用与 UserControl 连接的 ViewModel?这样你就不需要一个 Dependency 属性来让你的代码更容易阅读。 这是一个糟糕的建议。 UserControl - 与任何其他控件一样 - 不应该有自己的私有视图模型,这将与应用程序的视图模型结构断开连接。 【参考方案1】:您不需要在公开依赖属性的类中实现 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);
或者,将 Value 属性与一个 Binding Converter 绑定,该转换器从 Rating Value 创建一个字符串。
或者,可能是最简单的,直接访问应该更新的 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);
【讨论】:
以上是关于有没有更简单的方法来更新 WPF 中的相关属性?的主要内容,如果未能解决你的问题,请参考以下文章
WPF DataGrid 单元格绑定到域对象中属性的属性未更新