首页 > 其他分享 >[WPF]MVVM的数据绑定

[WPF]MVVM的数据绑定

时间:2023-02-17 18:33:39浏览次数:48  
标签:ClassM 界面 MainViewVM MVVM MainView 绑定 WPF public

啥是MVVM?

我理解的MVVM是Model(数据),View(界面),ViewModel(数据与界面之间的桥梁)的缩写,是一种编程模式。前期需要多花一些时间去编辑绑定,在后期维护方便。只需要关注数据即可。如:传统的界面更新需要去刷新界面才能读取到最新数据,在MVVM模式下只需要关注数据的更改,在该模式下可以实现控制界面自动更新。

一.数据是如何绑定到界面的?一步一步来!

  • 1.创建一个WPF项目,如在VS2022下创建WPF应用程序。(其他版本类似)

  • 2.项目创建好后,这里先创建Model数据类型。新建一个Model文件夹,添加一个ClassModel类,在此类中我们就写3个字段。

  • 3.新建View文件夹,添加一个MainView.xaml界面。再把启动界面改成MainView.xaml,这时候可以把项目自动生成的MainWindow.xaml删除掉了。

  • 4.布局MainView界面。

<Page x:Class="WPFMVVM.View.MainView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WPFMVVM.View"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="500"
      Title="MainView" Background="AliceBlue" FontFamily="行楷">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <TextBlock
            Grid.Row="0"
            Grid.Column="0"
            HorizontalAlignment="Right"
            VerticalAlignment="Center"
            FontSize="50"
            Text="姓名:" />

        <TextBlock
            Grid.Row="0"
            Grid.Column="1"
            HorizontalAlignment="Left"
            VerticalAlignment="Center"
            FontSize="50"
            Foreground="#0078d4"
            Text="雅男" />

        <TextBlock
            Grid.Row="1"
            Grid.Column="0"
            HorizontalAlignment="Right"
            VerticalAlignment="Center"
            FontSize="50"
            Text="年龄:" />

        <TextBlock
            Grid.Row="1"
            Grid.Column="1"
            HorizontalAlignment="Left"
            VerticalAlignment="Center"
            FontSize="50"
            Foreground="#0078d4"
            Text="20" />
        <TextBlock
            Grid.Row="2"
            Grid.Column="0"
            HorizontalAlignment="Right"
            VerticalAlignment="Center"
            FontSize="50"
            Text="性别:" />

        <TextBlock
            Grid.Row="2"
            Grid.Column="1"
            HorizontalAlignment="Left"
            VerticalAlignment="Center"
            FontSize="50"
            Foreground="#0078d4"
            Text="女" />

        <Button
            Grid.Row="3"
            Grid.ColumnSpan="2"
            Width="300"
            Margin="10"
            Content="刷新"
            FontSize="30"
            FontWeight="Bold" 
            Background="Aqua"
            BorderBrush="Azure"/>
    </Grid>
</Page>

  • 5.以上界面的数据是写死的。我们需要将显示的地方绑定我们的数据。在绑定之前先建一个ViewModel文件夹。为了和MainView界面对应,要再添加一个MainViewVM类,在此类中我们使用刚创建的ClassMode数据模型,并在构造函数中初始化以下信息。
   public class MainViewVM
    {
        private ClassModel _classM;

        public ClassModel ClassM
        {
            get { return _classM; }
            set { _classM = value; }
        }
        public MainViewVM()
        {
            ClassM = new ClassModel();
            ClassM.Name = "王刚";
            ClassM.Age = 10;
            ClassM.Sex = "男";
        }
    }
  • 6.在MainView界面绑定ClassM的属性就行。
 <TextBlock
            Grid.Row="0"
            Grid.Column="1"
            HorizontalAlignment="Left"
            VerticalAlignment="Center"
            FontSize="50"
            Foreground="#0078d4"
            Text="{Binding ClassM.Name}" />

但是这时候运行项目,发现什么数据也没有。

这是因为数据和界面都有了,我们并没有把他们关联在一起。要把View(MainView)与ViewModel(MainViewVM)关联一起。在MainView.xaml.cs里添加using WPFMVVM.ViewModel引用。再指定MainView的DataContext即可:

using WPFMVVM.ViewModel;
namespace WPFMVVM.View
{
    public partial class MainView : Page
    {
        public MainView()
        {
            InitializeComponent();
            this.DataContext = new MainViewVM();
        }}}

启动解决方案,发现数据已经绑定上去了。

二.属性变更

  • 1.MVVM是数据驱动的,我们现在改变以下属性数据,看看界面效果。先简单的给button添加一个click事件:
   <Button
            Grid.Row="3"
            Grid.ColumnSpan="2"
            Width="300"
            Margin="10"
            Content="刷新"
            FontSize="30"
            FontWeight="Bold" 
            Background="Aqua"
            BorderBrush="Azure"
            Click="Button_Click"/>

 public partial class MainView : Page
    {
        MainViewVM mainViewVM;
        public MainView()
        {
            InitializeComponent();
            mainViewVM = new MainViewVM();
            this.DataContext = mainViewVM;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            mainViewVM.ClassM.Name = "王大康";
            mainViewVM.ClassM = mainViewVM.ClassM;//需要再次给ClassM复制才会触发界面刷新
        }
    }
  • 2.我们还需要让属性具有通知界面更新的能力。WPF中让属性具备通知更新的能力,要让ViewModel继承类型INotifyPropertyChanged,并实现PropertyChanged属性。此例MainViewVM添加如下:
    public class MainViewVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        private void RaisePropertyChange(string propertyName)
        {
            PropertyChangedEventHandler hander = PropertyChanged;
            if (hander != null)
            {
                hander(this, new PropertyChangedEventArgs(propertyName));
            }
        }
  • 3.完成以上步骤,我们还需要在ViewModel的数据属性set中调用更新界面的方法RaisePropertyChanged:
        public ClassModel ClassM
        {
            get { return _classM; }
            set
            {
                _classM = value;
                RaisePropertyChange(nameof(ClassM));
            }
        }

现在点击Button按钮,可以实现信息的刷新!

三.点击事件

  • 1.WPF给我们提供了Command属性,当然在MVVM模式下我们要用Command替换Click方法:
        <Button
            Grid.Row="3"
            Grid.ColumnSpan="2"
            Width="300"
            Margin="10"
            Content="刷新"
            FontSize="30"
            FontWeight="Bold" 
            Background="Aqua"
            BorderBrush="Azure"
            Command="{Binding ClickAction}"
        />
  • 2.要实现绑定的ClickAction方法,需要继承ICommand接口。我们可以自己创建类型去实现 CanExecute、Execute、CanExecuteChanged接口。
    下面我们在MainViewVM.cs新建一个RealayCommand类:
  public class RelayCommand<T> : ICommand
    {
        /// <summary>
        /// 命令是否执行
        /// </summary>
        readonly Func<bool> _canExecute;
        /// <summary>
        /// 命令执行的方法
        /// </summary>
        readonly Action<T> _execute;
        /// <summary>
        /// 命令的构造函数
        /// </summary>
        /// <param name="canExecute"></param>
        /// <param name="execute"></param>
        public RelayCommand(Func<bool> canExecute, Action<T> execute)
        {
            _canExecute = canExecute;
            _execute = execute;
        }
        /// <summary>
        /// 判断命令是否可执行
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object? parameter)
        {
            if (_canExecute == null)
            {
                return true;
            }
            return _canExecute();
        }
        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(object parameter)
        {
            _execute((T)parameter);
        }
        /// <summary>
        /// 事件追加、移除
        /// </summary>
        public event EventHandler? CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
            remove
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;
                }
            }
        }
    }

这个类接收两个参数,一个是命令执行的方法,另一个是返回值方法。

  • 3.我们在MainViewVM下编写以下代码调用RelayCommand:
        /// <summary>
        /// 创建Button绑定的命令
        /// </summary>
        public ICommand ClickAction
        {
            get
            {
                return new RelayCommand<object>(CanUpdateExecute, UpdateNameExecute);
            }
        }
        /// <summary>
        /// 命令是否可执行
        /// </summary>
        /// <returns></returns>
        bool CanUpdateExecute()
        {
            return true;
        }
        /// <summary>
        /// 命令执行的方法
        /// </summary>
        /// <param name="parameter"></param>
        void UpdateNameExecute(object parameter) 
        {
                ClassM.Name = "王大康";
                ClassM = ClassM;
        }

此时我们运行程序,点击按钮,可以看到界面可以内容可以实现刷新了!

我们创建的RealayCommand是泛型类,执行命令的时候可以从界面把参数传过来。例如我们可以在Button添加CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}"属性,然后把信息传到后台使用:

前端代码:
  <Button
            Grid.Row="3"
            Grid.ColumnSpan="2"
            Width="300"
            Margin="10"
            Content="刷新"
            FontSize="30"
            FontWeight="Bold" 
            Background="Aqua"
            BorderBrush="Azure"
            Command="{Binding ClickAction}"
            CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
button 绑定的命令:
    void UpdateNameExecute(object parameter) 
        {
            Button? button =parameter as Button;//parameter前端绑定的Button
            if (button.Background !=Brushes.BlanchedAlmond) 
            {
                button.Background = Brushes.BlanchedAlmond ;
                ClassM.Name = "王大康";
                ClassM = ClassM;
            }
            else
            {
                button.Background=Brushes.DarkBlue; 
                ClassM.Name = "李小康";
                ClassM = ClassM;
            }
        }

到此,简单的MVVM数据绑定完成

标签:ClassM,界面,MainViewVM,MVVM,MainView,绑定,WPF,public
From: https://www.cnblogs.com/tuhong/p/17131195.html

相关文章

  • WPF中MVVM模式下loaded无法触发问题
    经过实践检测,当时View上设置了Window.SizeToContent="WidthAndHeight"时候<i:Interaction.Triggers><i:EventTriggerEventName="Loaded"><i:Invoke......
  • vue优点及双向数据绑定原理
    优点轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;简单易学:国人开发,中文文档,不存在语言障碍,易于理解和学习;双向数据绑定:保留了angular的特点,在数据......
  • 10分钟搞定简易MVVM
    实现一个简易的MVVM分为这么几步来1.类Vue:这个类接收的是一个options。el属性:根元素的iddata属性:双向绑定的数据。2.Dep类:subNode数组:存放所依赖这个属性的依......
  • WPF将超大图像分割成多个小图像使用多任务Task并行处理显示
    usingMicrosoft.Win32;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windo......
  • 10分钟了解MVVM,实现简易MVVM
    MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会......
  • WPF MVVM框架------ Prism中的区域导航(RegionManager)
    本次简单记录一下Prism中区域导航功能的使用第一步准备导航页面新建两个UserControl(RegionFirstView.xaml,RegionSecondView.xaml),作为导航的目标页面简单在两个页......
  • vue2 - 绑定class,绑定style
    1.绑定class样式字符串写法:适用于类名不确定,要动态获取数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。对象写法适用于:要绑定多个样式,个数不确定,名字......
  • WPF中使用LibVLCSharp.WPF 播放rtsp
    目录LibVLCSharp.WPF简介vlc:VideoView基本使用安装LibVLC播放rtsp引入命名空间xaml代码cs代码截图概述代码示例vlc:VideoView进阶使用空域问题......
  • 几个提升WPF应用程序冷启动性能的方法,建议收藏!(Part 2)
    在上文中(点击这里回顾>>),我们主要介绍了针对三个技术的WPF应用程序性能提升,本文将着重介绍针对DevExpressWPF界面控件研发的应用程序如何提升性能!PS:有用控件推荐~DevExpre......
  • C# WPF ListView 改变某行某列的背景颜色
    通过前端绑定Background属性实现,代码如下:<ListViewx:Name="listView1"ItemsSource="{Bindingitems}"Width="641"Margin="0,0,0,-5"ItemContainerStyle="{StaticRe......