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)
相关推荐
Dongwoo Jeong1 小时前
UI架构的历史与基础入门
c#·mvc·mvvm·mvp·mvi·architecture
mascon1 小时前
C#自定义扩展方法 及 EventHandler<TEventArgs> 委托
开发语言·c#
冰茶_5 小时前
掌握LINQ:查询语法与方法语法全解析
sql·学习·microsoft·微软·c#·linq
与火星的孩子对话5 小时前
Unity3D开发AI桌面精灵/宠物系列 【六】 人物模型 语音口型同步 LipSync 、梅尔频谱MFCC技术、支持中英文自定义编辑- 基于 C# 语言开发
人工智能·unity·c#·游戏引擎·宠物·lipsync
她说彩礼65万5 小时前
C# 中的锁
开发语言·c#
敲代码的 蜡笔小新9 小时前
【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀
unity·设计模式·c#·访问者模式
明耀10 小时前
WPF C# 用WebView加载H5页面(uniapp项目,vue项目)
uni-app·c#·wpf
我不是程序猿儿14 小时前
【C#】 lock 关键字
java·开发语言·c#
动感光博18 小时前
Unity序列化字段、单例模式(Singleton Pattern)
unity·单例模式·c#