wpf快速了解(2)事件驱动和数据驱动

勇哥注:

此系列贴子服务于C# winform开发工程师,帮助他们快速了解wpf技术,节省大家的学习成本。

因此,这个系列不是讲给初学者听的。

我们知道winform是C#的标准ui框架,wpf则是另一种ui框架,随着.net Core的流行,它会是今后的主流选择,我们必须学习它。


系列贴子导航:

wpf快速了解(1)基础开发环境

wpf快速了解(2)事件驱动和数据驱动

wpf快速了解(4)行为绑定,后续

wpf快速了解(5)数据集合的绑定



wpf的编程思想里有一条重要的,称为“数据驱动”。

我们知道winform是事件驱动的,wpf的数据驱动是明显有别于winform的一种方式。


下面我们做一件简单的事,引出“数据驱动”模式。


要求: 如果在一个文本框中输入了数值100,则自动将其文字颜色改为红色。

image.png


(一)用属性来实现


这样达的目的是,只要对属性Value赋值100,则文字变红色。

 private string _value;

        public string Value
        {
            get { return _value; }
            set 
            { 
                _value = value;
                this.TxtAddr.Text = value;
                if (value == "100")
                    this.TxtAddr.Foreground = Brushes.Red;
            }
        }


        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButRead_Click(object sender, RoutedEventArgs e)
        {
            this.Value = "100";
        }


(二)用封装的类来实现


我们使用面向对象的方式做一个封装。

它用构造函数传入了主窗体,以操作控件。

注意勇哥这里起的名字MainViewModel, 它是指视图模型,它个名字的意义在后面第(四)节可以知道。


    public class MainViewModel
    {
        MainWindow _win;
        public MainViewModel(MainWindow win)
        {
            _win = win;
        }

        private string _value;

        public string Value
        {
            get { return _value; }
            set
            {
                _value = value;
                _win.TxtAddr.Text = value;
                if (value == "100")
                    _win.TxtAddr.Foreground = Brushes.Red;
            }
        }
    }

调用方法:

  public MainViewModel model = null;

        public MainWindow()
        {
            InitializeComponent();
            model = new MainViewModel(this);
        }

        private void ButRead_Click(object sender, RoutedEventArgs e)
        {
            model.Value = "100";
        }


(三)控件属性绑定


例子二的控件操作其实可以使用xaml的绑定语法来实现。


首先我们把MainViewModel类改写一下。两个属性分别用于绑定文本框的Text和Foreground属性。

    public class MainViewModel
    {
        
        private string _value="0";

        public string Value
        {
            get { return _value; }
            set
            {
                _value = value;
            }
        }

        private Brush myColor= Brushes.Blue;

        public Brush MyColor
        {
            get { return myColor; }
            set { myColor= value; }
        }
    }

Xaml绑定语句如下:

注意几点:

  1.   要使用{},如果没有括号就是个普通字符

  2.   Value和MyColor是上面的MainViewModel类的两个属性。

  3.   绑定字符串这里VS2022还无法提供代码自动提示功能。

<TextBox Name="TxtAddr" Grid.Column="1" HorizontalAlignment="Left" Margin="84,131,0,0" 
TextWrapping="Wrap" Text="{Binding Value}" Foreground="{Binding MyColor}" VerticalAlignment="Top" Width="78"/>

光这样写上绑定语句还不够,此时还无法和MainViewModel类的两个属性建立关系。

你得在UI后台代码里为 DataContext赋值为MainViewModel类的实例。

        private MainViewModel model = new MainViewModel();

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = model;
        }

        private void ButRead_Click(object sender, RoutedEventArgs e)
        {
            model.Value = "100";
        }

现在运行后发现文本框显示出了默认的Value值和默认文本颜色MyColor,这证明绑定起作用了。

继续点击按钮让Value赋值100,此时问题来了。。。

你会发现文本框根本不更新内容,还是0。



(四)UI内容更新的事件通知


接下来解决更新ui的数据显示问题。

要点如下:

  1.    让MainViewModel类继承接口INotifyPropertyChanged,并且让接口自动实现

  2.   接口自动实现后会自动定义一个事件: public event PropertyChangedEventHandler? PropertyChanged;

     此事件是wpf内部维护的,你不用去实现它,你只需要直接去使用它。

  3.  属性Value和MyColor,当值改变时,都需要进行事件通知(通知UI控件更新这个值到控件上面)

     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));


    public class MainViewModel:INotifyPropertyChanged
    {
        
        private string _value="0";

        public string Value
        {
            get { return _value; }
            set
            {
                _value = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
                if (value == "100")
                    MyColor = Brushes.Red;
            }
        }

        private Brush myColor= Brushes.Blue;

        public event PropertyChangedEventHandler? PropertyChanged;

        public Brush MyColor
        {
            get { return myColor; }
            set { 
                myColor= value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MyColor"));
            }
        }
    }

调用者:

        private void ButRead_Click(object sender, RoutedEventArgs e)
        {
            model.Value = "100";
        }


到了第四步后,对于ui的操作,基本上我们就可以称为由事件驱动方式过渡为了数据驱动方式。

使用者一句赋值 model.Value = "100";  就已经完成控件内容更新(值由0变成100),以及逻辑处理后的控件更新(判断值为100则文字变红色) 


勇哥总结下上面的数据驱动的几个注意点:

 1.  数据驱动是由数据模型来推动UI动作的,上面的例子中的数据模型是MainViewModel类

      而传统的操作控件的方式是直接赋值。

  2. 数据驱动内部仍然使用的是事件通知完成UI更新

      因此,并不是说有了数据驱动,事件驱动就没有意义了。



本文测试源代码下载:


支付2元或购买VIP会员后,才能查看本内容!立即支付升级会员查询订单



--------------------- 

作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年5月    »
12345
6789101112
13141516171819
20212223242526
2728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864