手写一个WPF-MVVM

  1. 项目的结构,通常情况下项目会创建Command、Models、Services、ViewModels、Views这几个文件夹。文件夹的作用请看名字。  
  2. MainWindow的代码如下:
     1 <Window x:Class="WPF_MVVM.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:WPF_MVVM"
     7         mc:Ignorable="d"
     8         Title="MainWindow" Height="350" Width="525" FontSize="24">
     9     <Grid>
    10         <Grid.RowDefinitions>
    11             <RowDefinition Height="Auto"/>
    12             <RowDefinition Height="*"/>
    13         </Grid.RowDefinitions>
    14         <Menu>
    15             <MenuItem Header="文件">
    16                 <MenuItem Header="保存" Command="{Binding SaveCommand}"/>
    17             </MenuItem>
    18         </Menu>
    19         <!--<Button Content="保存"/>-->
    20         <Grid Grid.Row="1">
    21             <Grid.RowDefinitions>
    22                 <RowDefinition Height="Auto"/>
    23                 <RowDefinition Height="Auto"/>
    24                 <RowDefinition Height="Auto"/>
    25                 <RowDefinition Height="*"/>
    26             </Grid.RowDefinitions>
    27             <TextBox x:Name="tx1" Grid.Row="0" Background="LightBlue" Margin="4" Text="{Binding Path=Input1}"/>
    28             <TextBox x:Name="tx2" Grid.Row="1" Background="LightBlue" Margin="4" Text="{Binding Path=Input2}"/>
    29             <TextBox x:Name="tx3" Grid.Row="2" Background="LightBlue" Margin="4" Text="{Binding Path=Result}"/>
    30             <Button x:Name="addButton" Grid.Row="3" Content="" Command="{Binding AddCommand}"/>
    31         </Grid>
    32     </Grid>
    33 </Window>
  3. NotificationObject需要实现接口INotifyPropertyChanged,我理解他的作用是简化属性变更的通知方式。
     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Linq;
     5 using System.Text;
     6 using System.Threading.Tasks;
     7 
     8 namespace WPF_MVVM.ViewModels
     9 {
    10     class NotificationObject : INotifyPropertyChanged
    11     {
    12         public event PropertyChangedEventHandler PropertyChanged;
    13 
    14         public void RaisePropertyChanged(string propertyName)
    15         {
    16             if (this.PropertyChanged!=null)
    17             {
    18                 this.PropertyChanged.Invoke(this,new PropertyChangedEventArgs(propertyName));
    19             }
    20         }
    21     }
    22 }
  4. DelegateCommand需要实现接口ICommand。
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Windows.Input;
     7 
     8 namespace WPF_MVVM.Commands
     9 {
    10     class DelegateCommand : ICommand
    11     {
    12         /// <summary>
    13         /// 这里定义事件可通知绑定命令的元素IsEnabled是True还是False
    14         /// </summary>
    15         public event EventHandler CanExecuteChanged
    16         {
    17             add { CommandManager.RequerySuggested += value; }
    18             remove { CommandManager.RequerySuggested -= value; }
    19         }
    20 
    21         public bool CanExecute(object parameter)
    22         {
    23             if (this.CanExecuteFunc==null)
    24             {
    25                 return true;
    26             }
    27 
    28             return this.CanExecuteFunc(parameter);
    29         }
    30         public void Execute(object parameter)
    31         {
    32             if (this.ExecuteAction == null)
    33             {
    34                 return;
    35             }
    36 
    37             this.ExecuteAction(parameter);
    38         }
    39         public Action<object> ExecuteAction { get; set; }
    40         public Func<object,bool> CanExecuteFunc { get; set; }
    41     }
    42 }
  5. MainWindowViewModel需要继承于类NotificationObject,通过对属性set的操作中添加this.RaisePropertyChanged("Input1");
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using Microsoft.Win32;
     7 using WPF_MVVM.Commands;
     8 
     9 namespace WPF_MVVM.ViewModels
    10 {
    11     class MainWindowViewModel:NotificationObject
    12     {
    13         private double input1;
    14         public double Input1
    15         {
    16             get { return input1;}
    17             set
    18             {
    19                 input1 = value;
    20                 this.RaisePropertyChanged("Input1");
    21             }
    22         }
    23 
    24         private double input2;
    25         public double Input2
    26         {
    27             get { return input2; }
    28             set
    29             {
    30                 input2 = value;
    31                 this.RaisePropertyChanged("Input2");
    32             }
    33         }
    34 
    35         private double result;
    36         public double Result
    37         {
    38             get { return result; }
    39             set
    40             {
    41                 result = value;
    42                 this.RaisePropertyChanged("Result");
    43             }
    44         }
    45         public DelegateCommand AddCommand { get; set; }
    46         public DelegateCommand SaveCommand { get; set; }
    47         private void Add(object parameter)
    48         {
    49             this.Result = this.Input1 + this.Input2;
    50         }
    51 
    52         private bool CanAdd(object parmeter)
    53         {
    54             if (this.Input1!=0 && this.Input2!=0)
    55             {
    56                 return true;
    57             }
    58             else
    59             {
    60                 return false;
    61             }
    62         }
    63 
    64         private void Save(object parameter)
    65         {
    66             SaveFileDialog saveFileDialog=new SaveFileDialog();
    67             saveFileDialog.ShowDialog();
    68         }
    69         public MainWindowViewModel()
    70         {
    71             this.AddCommand=new DelegateCommand();
    72             this.AddCommand.ExecuteAction=new Action<object>(this.Add);
    73             this.AddCommand.CanExecuteFunc=new Func<object, bool>(this.CanAdd);
    74 
    75             this.SaveCommand=new DelegateCommand();
    76             this.SaveCommand.ExecuteAction=new Action<object>(this.Save);
    77         }
    78     }
    79 }
  6. 如何将MainWindow.xaml与MainWindowViewModel.cs结合呢?
    1. DataContext,先找当前控件的,然后向上查找对于的DataContext。
  7. MainWindow.xaml的后台代码实现MainWindow.xaml与MainWindowViewModel.cs结合
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Windows;
     7 using System.Windows.Controls;
     8 using System.Windows.Data;
     9 using System.Windows.Documents;
    10 using System.Windows.Input;
    11 using System.Windows.Media;
    12 using System.Windows.Media.Imaging;
    13 using System.Windows.Navigation;
    14 using System.Windows.Shapes;
    15 using WPF_MVVM.ViewModels;
    16 
    17 namespace WPF_MVVM
    18 {
    19     /// <summary>
    20     /// MainWindow.xaml 的交互逻辑
    21     /// </summary>
    22     public partial class MainWindow : Window
    23     {
    24         public MainWindow()
    25         {
    26             InitializeComponent();
    27             this.DataContext = new MainWindowViewModel();
    28         }
    29     }
    30 }

     

转载于:https://www.cnblogs.com/bjxingch/articles/9669905.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 WPF MVVM 架构中,可以使用 InvokeCommandAction 来触发 ViewModel 中的命令,并且可以传递一个参数。如果需要传递多个参数,可以使用以下方法: 1. 使用命令参数对象 定义一个类,包含需要传递的多个参数,例如: ``` public class CommandParameter { public string Parameter1 { get; set; } public int Parameter2 { get; set; } } ``` 在 XAML 中,使用该类作为 InvokeCommandAction 的 CommandParameter 属性的值: ``` <i:InvokeCommandAction Command="{Binding MyCommand}" CommandParameter="{Binding CommandParameter}" /> ``` 在 ViewModel 中,命令的 Execute 方法可以接收该类的实例作为参数: ``` public RelayCommand<CommandParameter> MyCommand { get; set; } public void MyCommandExecute(CommandParameter parameter) { // 使用参数 } ``` 2. 使用触发事件的参数 在 XAML 中,可以使用 EventTrigger 触发一个事件,并且可以使用 EventTrigger 的 EventArgsConverter 属性将事件参数转换为需要的类型。例如: ``` <i:Interaction.Triggers> <i:EventTrigger EventName="MyEvent"> <i:InvokeCommandAction Command="{Binding MyCommand}"> <i:InvokeCommandAction.CommandParameter> <MultiBinding Converter="{StaticResource MyConverter}"> <Binding Path="Parameter1" /> <Binding Path="Parameter2" /> </MultiBinding> </i:InvokeCommandAction.CommandParameter> </i:InvokeCommandAction> </i:EventTrigger> </i:Interaction.Triggers> ``` 在这里,使用 MultiBinding 将多个绑定值传递给一个转换器。转换器将这些值转换为需要的类型,并且将它们封装到一个对象中,然后作为命令的参数传递给 ViewModel。 在 ViewModel 中,命令的 Execute 方法可以接收该对象作为参数: ``` public RelayCommand<MyParameter> MyCommand { get; set; } public void MyCommandExecute(MyParameter parameter) { // 使用参数 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值