概述
简介
重写D3dPotrace
的UI界面, 要实现以下功能
1. 拖动滑条时右面的文本框随之变化
2. 修改参数时下面的图像随之变化
3. 通过按钮可以设置默认值
数据绑定的问题
数据绑定就使用VM模式, 举一个例子
// PotraceParams.cs
namespace PotraceUI
{
class PotraceParams
{
public int IgnoreAreaPixels;
public double Tolerance;
public double CornerThreshold;
public int Threshold;
public int TurnPolicy;
public bool Optimizing;
// ...
}
class PotraceParamsVM
{
private PotraceParams obj = new PotraceParams();
public string IgnoreAreaPixels
{
get { return obj.IgnoreAreaPixels.ToString(); }
set {
ConvertHelper.String2IntCheck(value, ref obj.IgnoreAreaPixels);
}
}
// ...
}
}
// MainWindow.xaml.cs
txtIgnoreArea.Binding(paramsVM, "IgnoreAreaPixels");
/// Utils.cs
namespace PotraceUI
{
static public class BindingHelper
{
static public void Binding(this TextBox control, object obj, string property)
{
var _binding = new Binding
{
Source = obj,
Path = new PropertyPath(property)
};
control.SetBinding(TextBox.TextProperty, _binding);
}
//...
}
}
这样做有什么问题?
只使用控件来修改参数(单向绑定)时完全没有问题…要反过来很麻烦
1. 修改默认值, 控件的值不会显示
2. 滑动条和文本框不好联动
一开始只给滑动条右边的文本框绑定到数据源,滑动条使用Value="{Binding ElementName=txtThreshold,Path=Text}"
来绑定到文本框元素,看起来挺棒的
设置为默认值的问题
设置为默认值真的很简单,只需要
class PotraceParams
{
public void SetDefaultValues()
{
IgnoreAreaPixels = 2;
Tolerance = 0.2;
CornerThreshold = 1.0;
Optimizing = true;
TurnPolicy = 0;
Threshold = 50;
}
}
但这样变化传递不到UI控件上。
实现INotifyPropertyChanged
接口即可
class PotraceParamsVM : INotifyPropertyChanged
{
private PotraceParams obj = new PotraceParams();
public event PropertyChangedEventHandler PropertyChanged;
public void SetDefaultValues()
{
obj.SetDefaultValues();
PropertyChanged(this, new PropertyChangedEventArgs("IgnoreAreaPixels"));
PropertyChanged(this, new PropertyChangedEventArgs("Tolerance"));
PropertyChanged(this, new PropertyChangedEventArgs("CornerThreshold"));
PropertyChanged(this, new PropertyChangedEventArgs("Optimizing"));
PropertyChanged(this, new PropertyChangedEventArgs("TurnPolicy"));
PropertyChanged(this, new PropertyChangedEventArgs("Threshold"));
}
}
将属性变化时间发送出去,UI接受后更新控件的值
随参数变化刷新预览
这是一个显然的Observer模式…
public partial class MainWindow : Window
{
private PotraceParamsVM paramsVM = new PotraceParamsVM();
public MainWindow()
{
InitializeComponent();
InitializeControls();
paramsVM.PropertyChanged += new PropertyChangedEventHandler(ParamsObserver);
}
private void ParamsObserver(object sender, PropertyChangedEventArgs e)
{
((PotraceParamsVM)sender).ExportParams();
RefreshImages();
}
这样就搞定了
再来说滑动条数据绑定的问题
仍然在只给文本框绑定数据源的状态下:
要让预览刷新,添加一个事件监听
private void InitializeControls()
{
sdThreshold.AddHandler(Slider.ValueChangedEvent, new RoutedEventHandler(SliderObserver), true);
}
private void SliderObserver(object sender, RoutedEventArgs e)
{
paramsVM.ExportParams();
RefreshImages();
}
拖动滑动条预览不断刷新,然而并没有什么用,图像根本就没有变化
滑动条的修改根本没有传递到数据源
上面的Binding方式,只有手动修改控件的值时才会传递给数据源(猜测可能是失焦事件触发),通过其他方式修改值并不会传递,需要再加一个数据绑定
删除之前在xaml中到元素的绑定,再进行修改
// PotraceParams.cs
public string Threshold
{
get { return obj.Threshold.ToString(); }
set {
ConvertHelper.String2IntCheck(value, ref obj.Threshold, 0, 100);
PropertyChanged(this, new PropertyChangedEventArgs("Threshold"));
PropertyChanged(this, new PropertyChangedEventArgs("ThresholdInt"));
}
}
public int ThresholdInt
{
get { return obj.Threshold; }
set
{
obj.Threshold = value;
PropertyChanged(this, new PropertyChangedEventArgs("Threshold"));
PropertyChanged(this, new PropertyChangedEventArgs("ThresholdInt"));
}
}
sdThreshold.Binding(paramsVM, "ThresholdInt");
要让滑动条和文本框一起活动,就要多增加一个通知事件了
最后
以上就是眯眯眼果汁为你收集整理的WPF通过INotifyPropertyChanged增强双向绑定的全部内容,希望文章能够帮你解决WPF通过INotifyPropertyChanged增强双向绑定所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复