我是靠谱客的博主 眯眯眼果汁,最近开发中收集的这篇文章主要介绍WPF通过INotifyPropertyChanged增强双向绑定,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

简介

重写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增强双向绑定所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部