If you’re doing any significant amount of MVVM / XAML work, then I hope you’ll find these Visual Studio snippets useful.
This first snippet creates a backing field, a property with a simple getter, and a setter that also calls RaiseNotifyPropertyChanged. This would usually be created in a ViewModel.
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets mlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>MVVM Property</Title> <Author>Phil Chuang</Author> <Description>A snippet for generating a backed Property that calls RaisePropertyChanged</Description> <HelpUrl></HelpUrl> <Shortcut>mvvmprop</Shortcut> </Header> <Snippet> <Declarations> <Literal Editable="true"> <ID>Type</ID> <ToolTip>Property type</ToolTip> <Default>Object</Default> <Function> </Function> </Literal> <Literal Editable="true"> <ID>PropertyName</ID> <ToolTip>Property name</ToolTip> <Default>Property</Default> <Function> </Function> </Literal> </Declarations> <Code Language="CSharp"> <![CDATA[private $Type$ my$PropertyName$; public $Type$ $PropertyName$ { get { return my$PropertyName$; } set { my$PropertyName$ = value; RaisePropertyChanged (() => $PropertyName$); } }]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets>
This snippet also has a shortcut. So you can be typing along in your ViewModel class, and you can quickly add a property by
- typing
mvvmprop
, and hitting tab - typing the Type of the property, such as
String
, and hitting tab - typing the name of the property, such as
FirstName
, and hitting tab
This creates the following code:
private String myFirstName; public String FirstName { get { return myFirstName; } set { myFirstName = value; RaisePropertyChanged (() => FirstName); } }
(Don’t worry about RaisePropertyChanged (() => $PropertyName$)
, that’ll get explained later)
The next snippet creates a static DependencyProperty and related instance property, which would usually go on a UserControl.
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets mlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>MVVM Dependency Property</Title> <Author>Phil Chuang</Author> <Description>A snippet for generating a Dependency Property</Description> <HelpUrl></HelpUrl> <Shortcut>mvvmdepprop</Shortcut> </Header> <Snippet> <Declarations> <Literal Editable="true"> <ID>PropertyType</ID> <ToolTip>Property type</ToolTip> <Default>Object</Default> <Function> </Function> </Literal> <Literal Editable="true"> <ID>PropertyName</ID> <ToolTip>Property name</ToolTip> <Default>Property</Default> <Function> </Function> </Literal> <Literal default="true" Editable="false"> <ID>ClassName</ID> <ToolTip>Class name</ToolTip> <Function>ClassName()</Function> <Default>ClassNamePlaceholder</Default> </Literal> </Declarations> <Code Language="CSharp"> <![CDATA[public $PropertyType$ $PropertyName$ { get { return ($PropertyType$) GetValue ($PropertyName$Property); } set { SetValue ($PropertyName$Property, value); } } public static readonly DependencyProperty $PropertyName$Property = DependencyProperty.Register ( INotifyPropertyChangedHelper.GetPropertyName (($ClassName$ c) => c.$PropertyName$), typeof ($PropertyType$), typeof ($ClassName$), new PropertyMetadata (null, On$PropertyName$Changed)); private static void On$PropertyName$Changed (DependencyObject d, DependencyPropertyChangedEventArgs e) { var instance = d as $ClassName$; if (instance == null) return; var oldValue = ($PropertyType$) e.OldValue; var newValue = ($PropertyType$) e.NewValue; // TODO implement }]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets>
The shortcut for this snippet is mvvmdepprop
, and it’ll behave exactly the same as the first snippet.
And last but not least, I’ve included a static class with helper methods for determining a property name via reflection at runtime. This is great because you won’t have to worry about magic strings any more, any change to a property name will get noticed at compile-time.
public static class INotifyPropertyChangedHelper { public static String GetPropertyName<T> (Expression<Func<T>> propertyExpression) { if (propertyExpression == null) throw new ArgumentNullException ("propertyExpression"); if (propertyExpression.Body.NodeType == ExpressionType.MemberAccess) { var memberExpr = (MemberExpression) propertyExpression.Body; return memberExpr.Member.Name; } if (propertyExpression.Body.NodeType == ExpressionType.Convert && propertyExpression.Body is UnaryExpression && ((UnaryExpression) propertyExpression.Body).Operand.NodeType == ExpressionType.MemberAccess) { var memberExpr = (MemberExpression) ((UnaryExpression) propertyExpression.Body).Operand; return memberExpr.Member.Name; } throw new Exception (String.Format ("Expected MemberAccess expression, got {0}", propertyExpression.Body.NodeType)); } public static String GetPropertyName<T, V> (Expression<Func<T, V>> propertyExpression) { if (propertyExpression == null) throw new ArgumentNullException ("propertyExpression"); if (propertyExpression.Body.NodeType == ExpressionType.MemberAccess) { var memberExpr = (MemberExpression) propertyExpression.Body; return memberExpr.Member.Name; } if (propertyExpression.Body.NodeType == ExpressionType.Convert && propertyExpression.Body is UnaryExpression && ((UnaryExpression) propertyExpression.Body).Operand.NodeType == ExpressionType.MemberAccess) { var memberExpr = (MemberExpression) ((UnaryExpression) propertyExpression.Body).Operand; return memberExpr.Member.Name; } throw new Exception (String.Format ("Expected MemberAccess expression, got {0}", propertyExpression.Body.NodeType)); } }
All 3 files can be found at this https://gist.github.com/philchuang/6168400.
Leave a Reply