在依赖属性 WPF 上使用绑定时出现问题 [重复]
Posted
技术标签:
【中文标题】在依赖属性 WPF 上使用绑定时出现问题 [重复]【英文标题】:Problem using a binding on a dependency property WPF [duplicate] 【发布时间】:2022-01-13 22:16:56 【问题描述】:我正在尝试在 CustomView 类上使用 IsHighlighted 依赖项属性。当我传递一个硬布尔值时它按预期工作,但是当我传递一个绑定时它不起作用。有人知道为什么吗?
我还应该在 IsHighlighted 设置器中调用 OnPropertyChanged 吗?
MainWindow.xaml
<StackPanel>
<!-- The data context is set properly -->
<TextBlock Text="Binding Text" FontSize="50"/>
<!-- This works! -->
<views:CustomView IsHighlighted="true"/>
<!-- This does not! -->
<views:CustomView IsHighlighted="Binding Path=One"/>
</StackPanel>
MainWindowViewModel.cs
public class MainWindowViewModel : ViewModelBase
private string _text;
public string Text
get return _text;
set _text = value;
private bool _one;
public bool One
get return _one;
set _one = value;
public MainWindowViewModel()
Text = "bound text!";
One = true;
CustomView.xaml
<UserControl>
<Grid Background="Binding Path=CurrentBackground,
RelativeSource=RelativeSource FindAncestor,
AncestorType=x:Type local:CustomView, AncestorLevel=1">
<TextBlock Text="Binding IsHighlighted" FontSize="40"/>
</Grid>
</UserControl>
CustomView.xaml.cs
public partial class CustomView : UserControl
public CustomView()
InitializeComponent();
DataContext = this;
public static readonly DependencyProperty IsHighlightedProperty =
DependencyProperty.Register(
name: "IsHighlighted",
propertyType: typeof(bool),
ownerType: typeof(CustomView)
);
public bool IsHighlighted
get => (bool)GetValue(IsHighlightedProperty);
set => SetValue(IsHighlightedProperty, value);
public Brush CurrentBackground
get
if (IsHighlighted)
return new SolidColorBrush(Colors.Yellow); // highlighted
else
return new SolidColorBrush(Colors.White); // not highlighted
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
【问题讨论】:
IsHighlighted="Binding Path=One"
不起作用,因为当前 DataContext 对象 - 即 Binding 的源对象 - 没有公开 One 属性(或者应该将其称为 On
?)。这是因为您已明确设置 DataContext 以保存对控件的引用,而不是 MainWindow 的视图模型。具有可绑定属性的控件永远不应显式设置其自己的 DataContex,因为这会破坏控件属性的任何标准、基于 DataContext 的绑定。
当您在调试模式下运行应用程序时,您应该已经注意到 Visual Studio 的输出窗口中出现数据绑定错误消息。
【参考方案1】:
首先删除行DataContext = this;
。用户控件将从其父级继承 DataContext
(在本例中为 MainWindow.xaml
,上下文为 MainViewModel
)。
另一个问题是您正确地将 DataContext 设置为您的MainWindow
。你设置了DataContext
的MainWindow.xaml
喜欢吗
this.DataContext = new MainWindowViewModel();
如果没有,请在 MainWindow.cs
的某个地方执行此操作(例如在构造函数中)。 DataContext
属性是绑定的默认来源。
https://docs.microsoft.com/en-us/dotnet/api/system.windows.frameworkelement.datacontext?view=windowsdesktop-6.0
第二件事是,您需要在 MainWindowViewModel
One
属性设置器中调用 PropertyChanged
。
public bool One
get return _one;
set
_one = value;
OnPropertyChanged();
我期待您的ViewModelBase
正在实现INotifyPropertyChanged
接口。如果没有,您将需要实施它。在您的情况下,它可以在没有 INotifyPropertyChanged
实现的情况下工作,因为您在构造函数中设置了 One
属性。但是当您想在 ViewModel 中的某些逻辑中更改此属性时,您需要通知视图 One
属性正在更改/更改(您将使用 INotifyPropertyChanged 接口实现来完成)。
https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=net-6.0
对 Xaml 中这些代码行的注释。
<Grid Background="Binding Path=CurrentBackground,
RelativeSource=RelativeSource FindAncestor,
AncestorType=x:Type local:CustomView, AncestorLevel=1">
如何更改背景的更好方法是创建一个类似 ValueConverter 的方法。
public class BackgroundConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
return (bool)value ? new SolidColorBrush(Colors.Yellow) : SolidColorBrush(Colors.White);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotImplementedException();
用法:
<Grid Background="Binding IsHighlighted,
RelativeSource=RelativeSource AncestorType=local:CustomView,
Converter=StaticResource BackgroundConverter">
【讨论】:
比转换器更好的是 DataTrigger。在任何一种情况下,请注意背景属性与 IsHighlighted 的绑定也需要RelativeSource=RelativeSource AncestorType=local:CustomView
。
为什么绑定也需要RelativeSource=RelativeSource AncestorType=local:CustomView
?它是 MainViewModel 的一个属性,所以你可以像 Background="Binding IsHighlighted, Converter=StaticResource BackgroundConverter"
一样直接绑定它。哦,我错过了什么?
阅读问题。 IsHighlighted 在 CurrentBackground 之前声明。
这是一个糟糕的建议。控件不应该知道特定的视图模型。它应该公开像 IsHighlighted 这样的可绑定属性。
我已经代表您这样做了。考虑以网格样式显示 DataTrigger,以了解如何在没有转换器的情况下实现这一点。以上是关于在依赖属性 WPF 上使用绑定时出现问题 [重复]的主要内容,如果未能解决你的问题,请参考以下文章