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)
相关推荐
Aevget2 小时前
界面控件DevExpress WPF v25.1新版亮点:AI功能的全面升级
c#·.net·wpf·界面控件·devexpress·ui开发
Archy_Wang_13 小时前
Hangfire 入门与实战:在 .NET Core 中实现可靠后台任务处理
c#·.netcore
爱编程的鱼6 小时前
想学编程作为今后的工作技能,学哪种语言适用性更强?
开发语言·算法·c#·bug
清风与日月7 小时前
c#事件委托示例
开发语言·c#
用户3721574261357 小时前
C# 实现在 Excel 中高效生成和操作表格
c#
csdn_aspnet7 小时前
C# 金字塔体积计算程序(Program for volume of Pyramid)
c#
William_cl8 小时前
C# ASP.NET MVC Model 分类:数据传输对象(DTO)—— 跨层传数的 “精简快递“
c#·asp.net·mvc
zwjapple9 小时前
Kafka 从入门到精通完整指南
c#·linq
唐青枫10 小时前
C#.NET SemaphoreSlim 深入解析:轻量级异步锁与并发控制
c#·.net
我是苏苏14 小时前
C#高级:程序查询写法性能优化提升策略(附带Gzip算法示例)
开发语言·算法·c#