我现在拥有的是扩展WPF工具包拾色器。当我在颜色选择器中选择颜色时,边框的颜色会更改为所选颜色。现在可以使用,请参阅以下gif:
有一些问题。当我删除INotifyPropertyChanged
界面和OnPropertyChanged()
方法时,一切仍然正常(为什么?!它不应该,对吧?)
此外,当我在MyStyle类的BackgroundColor属性的setter中添加断点时,该属性不会更新。它应该更新,因为我将它绑定到以下行:b.Path = new PropertyPath(nameof(BackgroundColor));
我的问题是:
我有以下ViewModel:
public class BoxViewModel : INotifyPropertyChanged
{
private string _backgroundcolor;
public string Description { get; set; }
public string BackgroundColor
{
get
{
return _backgroundcolor;
}
set
{
_backgroundcolor = value;
OnPropertyChanged();
}
}
/// <summary>
/// Occurs when [property changed].
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
适用于以下型号:
public class Box : MyStyle
{
Canvas _label;
Border _border;
string _description;
BoxViewModel vm;
public override void Draw(Canvas label)
{
_label = label;
_border = new Border();
_border.BorderBrush = BorderColorBrush;
_border.Background = BackgroundColorBrush;
_border.Width = Width;
_border.Height = Height;
//
_border.DataContext = vm;
Binding b = new Binding();
b.Source = vm;
b.Path = new PropertyPath(nameof(BackgroundColor));
b.Mode = BindingMode.TwoWay;
b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding(_border, Border.BackgroundProperty, b);
label.Children.Add(_border);
}
internal override void AddInputs(ItemsControl inputPanel)
{
vm = new BoxViewModel()
{
Description = _description,
BackgroundColor = BackgroundColor
};
inputPanel.Items.Add(vm);
}
}
然后MyStyle是一个带有一堆属性的抽象类,比如BackgroundColor one:
public abstract class MyStyle
{
string _BackgroundBrush;
string _BackgroundColor;
.....
public string BorderColor
{
get { return _BorderColor; }
set
{
_BorderColor = value;
BorderColorBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value != null ? BorderColor : "#FFFFFFFF"));
}
}
public SolidColorBrush BorderColorBrush { get; set; }
public string BackgroundColor {
get { return _BackgroundColor; }
set {
_BackgroundColor = value;
BackgroundColorBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value != null ? BackgroundColor : "#FFFFFFFF"));
}
}
public SolidColorBrush BackgroundColorBrush { get; set; }
.....
}
修改
它会更新BoxViewModel.BackgroundColor
属性,并在更改颜色时调用这些setter和getter。 MyStyle.BackgroundColor
没有任何改变也没有改变。它与数据上下文或绑定属性有什么关系吗?来自mystyle类的BackgroundColor字符串和BackgroundColors都应该更改。
答案 0 :(得分:2)
查看this。
很抱歉花了这么长时间回复,实际上你遇到了WPF的另一个隐藏方面,就是它WPF的数据绑定引擎将数据绑定到PropertyDescriptor实例,如果源对象是普通CLR,它将包装source属性对象并没有实现INotifyPropertyChanged 接口。数据绑定引擎将尝试通过PropertyDescriptor.AddValueChanged()方法订阅属性更改事件。当目标数据绑定元素更改属性值时,数据绑定引擎将调用PropertyDescriptor.SetValue()方法将更改后的值传回源属性,并且它将同时引发ValueChanged事件以通知其他订阅者(在本例中,其他订阅者将是ListBox中的TextBlock。
如果您正在实施INotifyPropertyChanged,那么您完全有责任在需要绑定到UI的数据的每个属性集中实现更改通知。否则,更改将不会像您期望的那样同步。
希望这会让事情稍微清楚一点。
所以基本上你可以做到这一点,只要它是一个普通的CLR对象。
答案 1 :(得分:2)
这似乎是WPF绑定引擎的一个功能。它检测到您有多个绑定到数据源(VM)的同一实例的控件,并且这些绑定中的至少一个处于TwoWay模式。当绑定更新源属性时,绑定引擎会自动更新其他绑定控件,而无需任何通知。
对于不通过绑定发起的更改(代码中执行的更改),将需要INotityPropertyChanged。
我用一个简单的WPF应用程序对此进行了测试,该应用程序有两个文本框绑定(双向)到没有INPC实现的POCO视图模型。更新任一文本框都会更改另一个文本框的内容,而没有明显的通知机制。