C# 是否可以让WPF中的usercontrol接收绑定类上的(多个)属性已更改的通知?
我有一个usercontrol,它在绑定类上使用多个属性。如果此类上的任何属性发生更改,我将更新控件 INotifyPropertyChanged仅在直接绑定到属性时有效。(这将起作用,但我必须为控件的每个实例绑定多个属性) 下面是我遇到的问题的简化版本。DirectProperty按预期工作。ParentPropertyChangedCallback()仅在将ParentClass分配给用户控件时激发,而不是在任何属性更改时激发 请告诉我我做了什么蠢事=) UserControl1.xaml.csC# 是否可以让WPF中的usercontrol接收绑定类上的(多个)属性已更改的通知?,c#,wpf,xaml,user-controls,inotifypropertychanged,C#,Wpf,Xaml,User Controls,Inotifypropertychanged,我有一个usercontrol,它在绑定类上使用多个属性。如果此类上的任何属性发生更改,我将更新控件 INotifyPropertyChanged仅在直接绑定到属性时有效。(这将起作用,但我必须为控件的每个实例绑定多个属性) 下面是我遇到的问题的简化版本。DirectProperty按预期工作。ParentPropertyChangedCallback()仅在将ParentClass分配给用户控件时激发,而不是在任何属性更改时激发 请告诉我我做了什么蠢事=) UserControl1.xaml.
public partial class UserControl1
{
public static readonly DependencyProperty DirectPropertyProperty =
DependencyProperty.Register(
"DirectProperty",
typeof(bool),
typeof(UserControl1),
new PropertyMetadata(default(bool), DirectPropertyChangedCallBack));
public static readonly DependencyProperty ParentClassProperty =
DependencyProperty.Register(
"ParentClass",
typeof(ParentClass),
typeof(UserControl1),
new PropertyMetadata(default(ParentClass), ParentPropertyChangedCallback));
public UserControl1()
{
InitializeComponent();
}
public bool DirectProperty
{
get { return (bool)GetValue(DirectPropertyProperty); }
set { SetValue(DirectPropertyProperty, value); }
}
public ParentClass ParentClass
{
get { return (ParentClass)GetValue(ParentClassProperty); }
set{ SetValue(ParentClassProperty, value); }
}
// private void parentProperty_Changed(object)
private static void DirectPropertyChangedCallBack(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var sourceObject = dependencyObject as UserControl1;
if (sourceObject == null) return;
//set rectangle 1 base on Direct Property
sourceObject.Rectangle1.Fill =
sourceObject.ParentClass.DirectProperty
? new SolidColorBrush(Colors.Green)
: new SolidColorBrush(Colors.Red);
}
private static void ParentPropertyChangedCallback(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var sourceObject = dependencyObject as UserControl1;
if (sourceObject == null) return;
//set rectangle 2 base on ParentClass Property
sourceObject.Rectangle2.Fill =
sourceObject.ParentClass.ParentProperty
? new SolidColorBrush(Colors.Green)
: new SolidColorBrush(Colors.Red);
//set rectangle 3 base on ChildClass Property
sourceObject.Rectangle3.Fill =
sourceObject.ParentClass.ChildClass.ChildProperty
? new SolidColorBrush(Colors.Green)
: new SolidColorBrush(Colors.Red);
}
}
ParentClass.cs
public class ParentClass :INotifyPropertyChanged
{
private ChildClass _childClass;
private bool _directProperty;
private bool _parentProperty;
public event PropertyChangedEventHandler PropertyChanged;
public ChildClass ChildClass
{
get { return _childClass; }
set
{
if (Equals(value, _childClass)) return;
_childClass = value;
OnPropertyChanged();
}
}
public bool DirectProperty
{
get { return _directProperty; }
set
{
if (value.Equals(_directProperty)) return;
_directProperty = value;
OnPropertyChanged();
}
}
public bool ParentProperty
{
get { return _parentProperty; }
set
{
if (value.Equals(_parentProperty)) return;
_parentProperty = value;
OnPropertyChanged();
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
ChildClass.cs
public class ChildClass : INotifyPropertyChanged
{
private bool _childProperty;
public event PropertyChangedEventHandler PropertyChanged;
public bool ChildProperty
{
get { return _childProperty; }
set
{
if (value.Equals(_childProperty)) return;
_childProperty = value;
OnPropertyChanged();
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
****劳动阶级
public class ParentClass :INotifyPropertyChanged
{
private ChildClass _childClass;
private bool _directProperty;
private bool _parentProperty;
public event PropertyChangedEventHandler PropertyChanged;
public ParentClass()
{
PropertyChanged += OnPropertyChanged;
}
public ChildClass ChildClass
{
get { return _childClass; }
set
{
if (Equals(value, _childClass)) return;
_childClass = value;
OnPropertyChanged();
_childClass.PropertyChanged += OnPropertyChanged;
DirectProperty = !DirectProperty;
}
}
public bool DirectProperty
{
get { return _directProperty; }
set
{
if (value.Equals(_directProperty)) return;
_directProperty = value;
OnPropertyChanged();
}
}
public bool ParentProperty
{
get { return _parentProperty; }
set
{
if (value.Equals(_parentProperty)) return;
_parentProperty = value;
OnPropertyChanged();
DirectProperty = ! DirectProperty;
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if (propertyChangedEventArgs.PropertyName == "DirectProperty") return;
// Properties that are bound to the UI you want to update
DirectProperty = ! DirectProperty;
}
}
您可以在类上执行的操作是订阅属性更改事件
INotifyPropertyChanged
使您能够订阅PropertyChanges
public ParentClass()
{
this.PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
// Properties that are bound to the UI you want to update
OnPropertyChanged("PROPERTYNAME");
}
现在,如果您只是更新每个已更改属性名称上的所有内容,就会触发任何已更改属性并重复该操作。您可以自定义它的行为方式,但想法就在那里。您还可以访问
PropertyChangedEventArgs
中的属性以了解正在更改的属性。您可以对类执行的操作是订阅属性更改事件INotifyPropertyChanged
使您能够订阅PropertyChanges
public ParentClass()
{
this.PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
// Properties that are bound to the UI you want to update
OnPropertyChanged("PROPERTYNAME");
}
现在,如果您只是更新每个已更改属性名称上的所有内容,就会触发任何已更改属性并重复该操作。您可以自定义它的行为方式,但想法就在那里。您还可以访问
PropertyChangedEventArgs
中的属性以了解正在更改的属性。您可以对类执行的操作是订阅属性更改事件INotifyPropertyChanged
使您能够订阅PropertyChanges
public ParentClass()
{
this.PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
// Properties that are bound to the UI you want to update
OnPropertyChanged("PROPERTYNAME");
}
现在,如果您只是更新每个已更改属性名称上的所有内容,就会触发任何已更改属性并重复该操作。您可以自定义它的行为方式,但想法就在那里。您还可以访问
PropertyChangedEventArgs
中的属性以了解正在更改的属性。您可以对类执行的操作是订阅属性更改事件INotifyPropertyChanged
使您能够订阅PropertyChanges
public ParentClass()
{
this.PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
// Properties that are bound to the UI you want to update
OnPropertyChanged("PROPERTYNAME");
}
现在,如果您只是更新每个已更改属性名称上的所有内容,就会触发任何已更改属性并重复该操作。您可以自定义它的行为方式,但想法就在那里。您还可以访问
PropertyChangedEventArgs
中的属性以了解正在更改的属性。如果您对视图模型(DataContext)的更改值感兴趣,可以使用多值转换器将视图模型的多个属性绑定到用户控件的单个属性。如果绑定中的任何属性发生更改,将调用转换器,您可以使用转换器在用户控件上设置单个值或不执行任何操作。您可以学习如何创建或使用多值转换器
样本xaml如下:
<UserControl1 >
<UserControl1.DirectProperty>
<MultiBinding Converter="{StaticResource myConverterName}">
<Binding Path="ChildClass"/>
<Binding Path="DirectProperty"/>
<Binding Path="ParentProperty"/>
</MultiBinding>
</UserControl1.DirectProperty>
</UserControl1>
假设您对视图模型(DataContext)的更改值感兴趣,可以使用多值转换器将视图模型的多个属性绑定到用户控件的单个属性。如果绑定中的任何属性发生更改,将调用转换器,您可以使用转换器在用户控件上设置单个值或不执行任何操作。您可以学习如何创建或使用多值转换器 样本xaml如下:
<UserControl1 >
<UserControl1.DirectProperty>
<MultiBinding Converter="{StaticResource myConverterName}">
<Binding Path="ChildClass"/>
<Binding Path="DirectProperty"/>
<Binding Path="ParentProperty"/>
</MultiBinding>
</UserControl1.DirectProperty>
</UserControl1>
假设您对视图模型(DataContext)的更改值感兴趣,可以使用多值转换器将视图模型的多个属性绑定到用户控件的单个属性。如果绑定中的任何属性发生更改,将调用转换器,您可以使用转换器在用户控件上设置单个值或不执行任何操作。您可以学习如何创建或使用多值转换器 样本xaml如下:
<UserControl1 >
<UserControl1.DirectProperty>
<MultiBinding Converter="{StaticResource myConverterName}">
<Binding Path="ChildClass"/>
<Binding Path="DirectProperty"/>
<Binding Path="ParentProperty"/>
</MultiBinding>
</UserControl1.DirectProperty>
</UserControl1>
假设您对视图模型(DataContext)的更改值感兴趣,可以使用多值转换器将视图模型的多个属性绑定到用户控件的单个属性。如果绑定中的任何属性发生更改,将调用转换器,您可以使用转换器在用户控件上设置单个值或不执行任何操作。您可以学习如何创建或使用多值转换器 样本xaml如下:
<UserControl1 >
<UserControl1.DirectProperty>
<MultiBinding Converter="{StaticResource myConverterName}">
<Binding Path="ChildClass"/>
<Binding Path="DirectProperty"/>
<Binding Path="ParentProperty"/>
</MultiBinding>
</UserControl1.DirectProperty>
</UserControl1>
如果可能的话,多绑定是最好的选择。在某些情况下,它不太实用或不方便,因此另一种选择是直接从viewmodel通过单个属性公开其他属性的集合。是的。我完全同意。如果可能的话,多绑定是一个不错的选择。在某些情况下,它不太实用或不方便,因此另一种选择是直接从viewmodel通过单个属性公开其他属性的集合。是的。我完全同意。如果可能的话,多绑定是一个不错的选择。在某些情况下,它不太实用或不方便,因此另一种选择是直接从viewmodel通过单个属性公开其他属性的集合。是的。我完全同意。如果可能的话,多绑定是一个不错的选择。在某些情况下,它不太实用或不方便,因此另一种选择是直接从viewmodel通过单个属性公开其他属性的集合。是的。我完全同意。我必须添加一个检查以防止无休止的循环,并且调用OnPropertyChanged不起作用,但是更改有界属性的值起作用。(Dependency Property vs INotify?)所以我有了一个可行的解决方案。ThanksI必须添加一个检查以防止无休止的循环,而调用OnPropertyChanged则没有