WPF 的几种 MVVM 绑定方式

INotifyPropertyChanged 绑定

在 ViewModel 中继承 INotifyPropertyChanged

ViewModel.cs

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp
{
    public class ViewModel : INotifyPropertyChanged
    {
        public string name;
       
        public string Name
        {
            get { return name; }
            set { name = value; OnPropertyChanged("Name"); }
        }

        public ObservableCollection<Student> stuList = new ObservableCollection<Student>();

        public ObservableCollection<Student> StuList
        {
            get { return stuList; }
            set { stuList = value; OnPropertyChanged("StuList"); }
        }

		public event PropertyChangedEventHandler? PropertyChanged;
        
        protected void OnPropertyChanged(string properName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(properName));
        }
        
        public ViewModel()
        {
            Name = "hello";
            Task.Run(async () =>
            {
                await Task.Delay(3000);
                Name = "no";
                stuList.Add(new Student() { Address = "12223", ClassName = "12223", UserName = "2" });

            });
        }
    }
}

XAML

xaml 复制代码
<Grid Grid.Row="0">
    <StackPanel>
        <TextBox  Text="{Binding Name}" />
        <TextBox  Text="{Binding Name}" />
        <TextBox  Text="{Binding Name}" />
        <Button Command="{Binding SavaCommand}" Height="30" />
    </StackPanel>
</Grid>
<Grid Grid.Row="1">
    <ListView x:Name="lv" ItemsSource="{Binding StuList, Mode=TwoWay}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding UserName}" />
                <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding ClassName}" />
                <GridViewColumn Header="Mail" Width="150" DisplayMemberBinding="{Binding Address}" />
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

MvvmLight 绑定(已经很久没有更新了)

在 ViewModel 中继承 ViewModelBase

引用程序集 using GalaSoft.MvvmLight;

csharp 复制代码
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.Text;

namespace WpfStudy.ViewModel
{
    public class CanvasViewModel: ViewModelBase
    {
        public string name;

        public string Name
        {
            get { return name; }
            set { name = value; base.RaisePropertyChanged(() => Name); }
        }
    }
}

事件绑定

可传参数

引入程序集

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

xaml 复制代码
 <Canvas x:Name="Canvas" Grid.Row="1" Background="Black">
     <i:Interaction.Triggers>
         <i:EventTrigger EventName="PreviewMouseWheel">
             <i:InvokeCommandAction Command="{Binding PreviewMouseWheelCommand}" CommandParameter="1"  />
         </i:EventTrigger>
     </i:Interaction.Triggers>
</Canvas>

InvokeCommandAction CommandParameter 属性可传传参

可传事件

引入程序集

http://schemas.microsoft.com/expression/2010/interactions

xaml 复制代码
<Canvas x:Name="Canvas" Grid.Row="1" Background="Black">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewMouseWheel">
            <m:EventToCommand Command="{Binding PreviewMouseWheelCommand}" PassEventArgsToCommand="True"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Canvas>

EventToCommand PassEventArgsToCommand 属性为True可传事件对象

可传参数和事件

引入程序集

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

可用此命名空间替换 http://schemas.microsoft.com/expression/2010/interactivityhttp://schemas.microsoft.com/expression/2010/interactions 两个命名空间

xaml 复制代码
<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True"/>
    </i:EventTrigger>
    <i:EventTrigger EventName="PreviewTextInput">
        <i:InvokeCommandAction Command="{Binding PreviewTextInputCommand}" CommandParameter="1"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

可以同时使用 PassEventArgsToCommandCommandParameter 两个属性

ViewModel 层

csharp 复制代码
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace WpfStudy.ViewModel
{
    public class CanvasViewModel: ViewModelBase
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; base.RaisePropertyChanged(() => Name); }
        }

        public RelayCommand<object> PreviewMouseWheelCommand { get; set; };


        public CanvasViewModel()
        {
            PreviewMouseWheelCommand = new RelayCommand<object>(PreviewMouseWheel);
        }


        private void PreviewMouseWheel(object e)
        {

        }
    } 
}

RelayCommand

引用程序集 using GalaSoft.MvvmLight.Command;

Tips:双向绑定的数据变更还是需要使用公用变量来变更绑定的值。

CommunityToolkit.Mvvm 绑定

微软推出的快速且模块化的 MVVM 库

在 ViewModel 中继承 ObservableObject

引用程序集 using CommunityToolkit.Mvvm.ComponentModel;

csharp 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace PrecisionToolset.ViewModels
{
    public class TestViewModel : ObservableObject
    {
        private string _status = string.Empty;
        public string Status
        {
            get => _status;
            set => SetProperty(ref _status, value);
        }

        public ICommand buttonCommand { get; }

        public TestViewModel() 
        { 
            Status = "Hello";
            buttonCommand = new RelayCommand<object>(ButtonClick);
        }

        private void ButtonClick(object b)
        {
            int a = 1;
        }
    }
}

事件绑定

使用 CommunityToolkit.Mvvm 的事件绑定方法和MvvmLight基本上一致。

XAML中可以引入 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 来实现可传入参数和事件。

XAML 中绑定的用法

CommandParameter 参数绑定

  • 传入当前组件的某一个属性:CommandParameter="{Binding Header, RelativeSource={RelativeSource Self}}"
  • 传入某一个其他组件对象:CommandParameter="{Binding ElementName=menuBtn}" (menuBtn 是一个按钮的x:name)
相关推荐
YuanlongWang4 小时前
c# 泛型的详细介绍
c#
嵌入式学习和实践6 小时前
C# WinForms 多窗口交互通信的示例-主窗口子窗口交互通信
c#·交互·主窗口-子窗口通信
专注VB编程开发20年6 小时前
C#,VB.NET数组去重复,提取键名和重复键和非重复键
c#·.net·linq·取唯一键·去重复·重复数量
YuanlongWang6 小时前
Entity Framework Core和SqlSugar的区别,详细介绍
c#
unicrom_深圳市由你创科技9 小时前
工业上位机,用Python+Qt还是C#+WPF?
python·qt·c#
偶尔的鼠标人20 小时前
Avalonia DataGrid 控件的LostFocus事件会多次触发
开发语言·c#
ytttr87320 小时前
C# 仿QQ聊天功能实现 (SQL Server数据库)
数据库·oracle·c#
future_studio1 天前
聊聊 Unity(小白专享、C# 小程序 之 图片播放器)
unity·小程序·c#
c#上位机1 天前
wpf中Grid的MouseDown 事件无法触发的原因
c#·wpf
CodeCraft Studio1 天前
国产化PDF处理控件Spire.PDF教程:如何在 C# 中从 HTML 和 PDF 模板生成 PDF
pdf·c#·html·.net·spire.pdf·pdf文档开发·html创建模板pdf