目录
基础类库
NotifyPropertyChanged 数据属性
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MvvmBase
{
class NotifyPropertyObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
#region 简单实现
//对事件进行简单封装
//public void RaisePropertyChanged(string propertyName)
//{
// if (propertyName != null)
// {
// //告诉Binding那个属性的值发生了变化
// this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
// }
//}
#endregion
#region 使用 ?. Null条件运算符进行简化
//简化
//public void SetProperty(string propertyName)
//{
// PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//}
#endregion
#region 配合Prism扩展进行封装
//配合Prism扩展进行封装 使用Prism扩展 语法糖propp
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
#endregion
}
}
MVVM DelegateCommand 命令属性
using System;
using System.Windows.Input;
namespace MvvmBase
{
class DelegateCommand : ICommand
{
#region 简单实现
//声明一个Action的委托,当Execute执行的时候,做一件事情
//public Action<object> ExeuteActio { get; set; }
//public Func<object, bool> CanExecuteFunc { get; set; }
//public event EventHandler CanExecuteChanged;
//public bool CanExecute(object parameter)
//{
// if (this.CanExecuteFunc == null)
// {
// return true;
// }
// this.CanExecuteFunc(parameter);
// return false;
//}
//public void Execute(object parameter)
//{
// if (this.ExeuteActio == null)
// {
// return;
// }
// this.ExeuteActio(parameter);
//}
#endregion
#region 使用拉姆达表达式 => ?. NULL条件运算符 ?? NULL合并运算符 进行简化
//简化版
private readonly Action<object> _executeAction;
private readonly Func<object, bool> _canExecuteAction;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecuteAction)
{
_executeAction = executeAction;
_canExecuteAction = canExecuteAction;
}
public void Execute(object parameter) => _executeAction(parameter);
public bool CanExecute(object parameter) => _canExecuteAction?.Invoke(parameter) ?? true;
public void InvokeCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
#endregion
}
}
使用PropertyChanged.Fody简化NotifyPropertyChanged
使用方法
- 通过Nuget安装PropertyChanged.Fody。
- 安装完成后,会在项目中,添加FodyWeavers.xml文件,这是Fody的配置文件。
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>
说明
项目中所有标记有[AddINotifyPropertyChangedInterface]特性,或者实现了INotifyPropertyChanged的类,都将自动在其属性中实现通知相关的代码,除非属性被显示标记为不通知。
- 程序中的代码:
[AddINotifyPropertyChangedInterface]
class VM_MainWindow
{
public int x { get; set; }
public int y { get; set; }
public string btn { get; set; }
public VM_MainWindow()
{
x = 10;
y = 20;
btn = "计算";
}
}
- 编译后的代码:
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using 测试2;
internal class VM_MainWindow : INotifyPropertyChanged
{
public int x
{
[CompilerGenerated]
get
{
return <x>k__BackingField;
}
[CompilerGenerated]
set
{
if (<x>k__BackingField != value)
{
<x>k__BackingField = value;
<>OnPropertyChanged(<>PropertyChangedEventArgs.x);
}
}
}
public int y
{
[CompilerGenerated]
get
{
return <y>k__BackingField;
}
[CompilerGenerated]
set
{
if (<y>k__BackingField != value)
{
<y>k__BackingField = value;
<>OnPropertyChanged(<>PropertyChangedEventArgs.y);
}
}
}
public string btn
{
[CompilerGenerated]
get
{
return <btn>k__BackingField;
}
[CompilerGenerated]
set
{
if (!string.Equals(<btn>k__BackingField, value, StringComparison.Ordinal))
{
<btn>k__BackingField = value;
<>OnPropertyChanged(<>PropertyChangedEventArgs.btn);
}
}
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
public VM_MainWindow()
{
x = 10;
y = 20;
btn = "计算";
}
[GeneratedCode("PropertyChanged.Fody", "3.2.9.0")]
[DebuggerNonUserCode]
protected void <>OnPropertyChanged(PropertyChangedEventArgs eventArgs)
{
this.PropertyChanged?.Invoke(this, eventArgs);
}
}
代码模板 Code Snippet
工具-》代码片段管理器-》CSharp-》Visual C#-》打开模板文件夹-》复制一个模板-》修改内容-》保存至代码文件夹中
数据属性 快捷方式propn
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propn</Title>
<Shortcut>propn</Shortcut>
<Description>属性和支持字段通知的代码片段</Description>
<Author>Fish Pond816</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>属性类型</ToolTip>
<Default>int</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>属性名</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>支持此属性的变量</ToolTip>
<Default>myVar</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private $type$ $field$;
public $type$ $property$
{
get { return $field$;}
set
{
$field$ = value;
this.RaisePropertyChanged("$property$");
}
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
命令属性 快捷方式pronc
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets
xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propc</Title>
<Shortcut>propc</Shortcut>
<Author>Fish Pond816</Author>
<Description>
使用Execute方法创建DelegateCommand属性
</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>fieldName</ID>
<ToolTip>
包含DelegateCommand的后备字段的名称
</ToolTip>
<Default>_fieldName</Default>
</Literal>
<Literal>
<ID>CommandName</ID>
<ToolTip>
DelegateCommand的名称
</ToolTip>
<Default>CommandName</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private DelegateCommand $fieldName$;
public DelegateCommand $CommandName$ =>
$fieldName$ ?? ($fieldName$ = new DelegateCommand(Execute$CommandName$));
void Execute$CommandName$(object commandParameter)
{
$end$
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
示例:
NotifyPropertyChanged类
class NotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName) => PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
}
DelegateCommand 类
class DelegateCommand : ICommand
{
private readonly Func<object, bool> _canExecuteAction;
private readonly Action<object> _executeAction;
public DelegateCommand(Action<object> executeAction, Func<object,bool> canExecuteAction = null)
{
_executeAction = executeAction;
_canExecuteAction = canExecuteAction;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)=> _canExecuteAction?.Invoke(parameter) ?? true;
public void Execute(object parameter) => _executeAction(parameter);
public void InvokeCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
View.Xaml
<StackPanel>
<TextBox Text="{Binding X}"/>
<TextBox Text="{Binding Y}"/>
<Button Command="{Binding AddCommadn}" Content="{Binding Btn}"/>
</StackPanel>
<!--C#代码-->
public MainWindowView()
{
InitializeComponent();
this.DataContext =new MainWindowViewModel();
}
ViewModel.cs:
class MainWindowViewModel:NotifyPropertyChanged
{
private int _x;
public int X
{
get { return _x; }
set {
_x = value;
this.RaisePropertyChanged("X");
}
}
private int _y;
public int Y
{
get { return _y; }
set {
_y = value;
this.RaisePropertyChanged("Y");
}
}
private string _btn;
public string Btn
{
get { return _btn; }
set {
_btn = value;
this.RaisePropertyChanged("Btn");
}
}
private DelegateCommand _addCommand;
public DelegateCommand AddCommadn =>
_addCommand ?? (_addCommand = new DelegateCommand(ExecuteAddCommadn));
void ExecuteAddCommadn(object commandParameter)
{
int Z = X + Y;
MessageBox.Show($"结果是:{Z}");
}
public MainWindowViewModel()
{
X = 20;
Y = 40;
Btn = "点击";
}
}