Wpf 第三方Mvvm包(mvvmLight/Microsoft.Toolkit.Mvvm/CommunityToolkit.Mvvm)

发布时间 2023-11-29 16:21:54作者: 天才卧龙

十年河东,十年河西,莫欺少年穷

学无止境,精益求精 

mvvmLight 和 Microsoft.Toolkit.Mvvm 已被Nuget弃用且不再更新,在此不作说明

CommunityToolkit.Mvvm 是 NetCore 版本引用包,详情参考:WPF MVVM框架:CommunityToolkit.Mvvm包使用介绍

1、wpf项目中使用 CommunityToolkit.Mvvm (NetCore3.1以上)

1.1、实现的界面

 界面中包含一个进度条,2个文本框,2个按钮,

靠上的文本框显示viewModel中的一个属性值,和进度条实现双向绑定,另一个文本框显示实时时间。

2个按钮,靠上的执行无参函数,靠下的执行有参函数

xaml如下:

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="Button" x:Key="baseStl">
            <Setter Property="Width" Value="200"/>
            <Setter Property="Height" Value="80"/>
            <Setter Property="Background" Value="Yellow"/>
            <Setter Property="FontSize" Value="22"/>

        </Style>
        <Style TargetType="Button" x:Key="Butn" BasedOn="{StaticResource baseStl}">
            <Setter Property="Content" Value="Btu"/>

        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <Slider x:Name="slider" Maximum="100" Minimum="0"  Margin="5" Value="{Binding wendu}"  ></Slider>
            <TextBox x:Name="textbox1" Margin="5" Height="30" Text="{Binding wendu}" />
            <Button x:Name="button" Style="{StaticResource Butn}"  Command="{Binding BtnCommand}" Width="300" Height="100" Content="执行无参数方法" />

            <Button x:Name="button2" Style="{StaticResource Butn}"  Command="{Binding Btn2Command}" CommandParameter="{Binding ElementName=timetextbox,Path=Text,Mode=TwoWay}" Width="300" Height="100" Content="执行带参数的方法" />

            <TextBox x:Name="timetextbox" Margin="5" Height="30" Text="{Binding CurrentTime}"  VerticalAlignment="Center"/>
        </StackPanel>
    </Grid>
</Window>
View Code

1.2、声明数据上下文

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

1.3、viewModel如下

    public class MainWindowModel : ObservableObject
    {
        public IRelayCommand BtnCommand { get; set; }
        public IRelayCommand<string> Btn2Command { get; set; }
        
        public MainWindowModel()
        {
            //进度条模式为20
            this.wendu = 20;
            StartUpdateTimer();
            BtnCommand = new RelayCommand(DoBtnCommand);
            Btn2Command = new RelayCommand<string>(DoBtn2Command);
             
        }
        public void DoBtn2Command(string param)
        {
            this.wendu = 50;
            MessageBox.Show(param);
        }

        public void DoBtnCommand()
        {
            this.wendu = 88;
            MessageBox.Show("进度条的值修改为88,进度条向前动了。");
        }
        private ushort _wendu;
        public ushort wendu
        {
            get { return this._wendu; }
            set
            {
                this._wendu = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        private string currentTime;

        public string CurrentTime { get => currentTime; set => SetProperty(ref currentTime, value); }
        //public string CurrentTime
        //{
        //    get { return this.currentTime; }
        //    set
        //    {
        //        SetProperty(ref currentTime, value);
        //    }
        //}
        private void StartUpdateTimer()
        {
            System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
            dispatcherTimer.Interval = TimeSpan.FromSeconds(1);
            dispatcherTimer.Tick += (a, b) => UpdateTime();
            dispatcherTimer.Start();
        }

        private void UpdateTime()
        {
            CurrentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }
View Code

1.4、说明如下:

viewModel 继承自 ObservableObject

MainWindowModel : ObservableObject

1、双向绑定声明属性如下:

        private ushort _wendu;
        public ushort wendu
        {
            get { return this._wendu; }
            set
            {
                this._wendu = value;
                this.OnPropertyChanged();
            }
        }

这里的this.OnPropertyChanged如下:

 可以看到,ObservableObject 实现了INotifyPropertyChanged, INotifyPropertyChanging接口,因此实现了双向绑定,这种做法使我们的代码更加简洁。

2、SetProperty 方法,顾名思义,这是设置属性的方法,我们实时显示当前时间的功能就用到了这个功能

        /// <summary>
        /// 设置属性
        /// </summary>
        private string currentTime;

        public string CurrentTime { get => currentTime; set => SetProperty(ref currentTime, value); }
        //public string CurrentTime
        //{
        //    get { return this.currentTime; }
        //    set
        //    {
        //        SetProperty(ref currentTime, value);
        //    }
        //}
        private void StartUpdateTimer()
        {
            System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
            dispatcherTimer.Interval = TimeSpan.FromSeconds(1);
            dispatcherTimer.Tick += (a, b) => UpdateTime();
            dispatcherTimer.Start();
        }

        private void UpdateTime()
        {
            CurrentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }

3、执行无参函数 及 有参函数

        public IRelayCommand BtnCommand { get; set; }
        public IRelayCommand<string> Btn2Command { get; set; }
        
        public MainWindowModel()
        {
            //进度条模式为20
            this.wendu = 20;
            StartUpdateTimer();
            BtnCommand = new RelayCommand(DoBtnCommand);
            Btn2Command = new RelayCommand<string>(DoBtn2Command);
             
        }
        public void DoBtn2Command(string param)
        {
            this.wendu = 50;
            MessageBox.Show(param);
        }

        public void DoBtnCommand()
        {
            this.wendu = 88;
            MessageBox.Show("进度条的值修改为88,进度条向前动了。");
        }

 这里重点说明下有参函数执行的过程

xaml如下

 这里携带的参数是 timetextbox的text值

 @天才卧龙的波尔卡