after reading this article, a have the following code in my PersonViewModel
class:
public Jurisdiction CountryResidence
{
get
{
return Model.CountryResidence;
}
set
{
if (Model.CountryResidence == value)
return;
else
{
Model.CountryResidence = value;
base.OnPropertyChanged("CountryResidence");
}
}
}
public Jurisdiction CountryBirth
{
get
{
return Model.CountryBirth;
}
set
{
if (Model.CountryBirth == value)
return;
else
{
Model.CountryBirth = value;
base.OnPropertyChanged("CountryBirth");
}
}
}
I also have CountryDomiciled
, CountryPassport
and LegalJurisdiction
, all with the same format. Similarly, I have lots of String
properties, all of which share their format.
This results in lots of samey code! However, I can't work out how to make this more concise.
Is there a better way to generate these properties that keeps them strongly typed?
I use snippet for Visual Studio, which generates property with backing storage and event raising for me. Simply create xml file with name propchanged
(or other name, if you wish) and following content:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propchanged</Title>
<Shortcut>propchanged</Shortcut>
<Description>Code snippet for property (with call to OnPropertyChanged) and backing field</Description>
<Author>lazyberezovsky</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>string</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>The variable backing this property</ToolTip>
<Default>myVar</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private $type$ $field$;
public $type$ $property$
{
get { return $field$;}
set
{
if ($field$ == value)
return;
$field$ = value;
OnPropertyChanged("$property$");
}
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
And put it to folder C:\Users\YourName\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets\
.
Next, I inherit my ViewModels from some base ViewModel, which implements INotifyPropertyChanged
inteface and provides protected method OnPropertyChanged
for generating `PropertyChanged' event.
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
}
}
Now when you type propchanged
in Visual Studio, it will ask you for property type and name, and generate code for you.
public class PersonViewModel : ViewModel
{
// type here 'propchanged' (or other shortcut assigned for snippet)
}
UPDATE:
Another option is generating code by AOP framework like PostSharp. In this case code will be generated and added during compilation (thus your classes will stay clean). Here is example of implementing INotifyProperty changed via PostSharp attributes:
[Notify]
public class PersonViewModel
{
public Jurisdiction CountryResidence { get; set; }
public Jurisdiction CountryBirth { get; set; }
}
UPDATE: NotifyPropertyWeaver is deprecated and continues its life as PropertyChanged.Fody. This is an absolute super cool way to solves this issue. It is a compile time only solution.
Here's something that will save you code and trouble: NotifyPropertyWeaver
Using the above, you can implement your properties without any INotifyPropertyChanged
related code, and a build step will handle the wiring up for you.
It's a simple project include (also available via Nuget) that will automatically inject the OnPropertyChanged
callbacks into the properties of any class that implements INotifyPropertyChanged
. It does it at compile time (so no runtime hit) and your code can just have auto-implemented properties (except in your case, where you're using a separate backing object).
It even includes the value equality check, so it covers the full logic. I haven't tested it with manually-implemented properties, but worth checking out.
EDIT: I have tested it now, and it works fine: a manually implemented property will "just work."
Not really what you're looking for, but as an aside you can save two lines per property by reversing your logic test:
public Jurisdiction CountryResidence
{
get
{
return Model.CountryResidence;
}
set
{
if (Model.CountryResidence != value)
{
Model.CountryResidence = value;
base.OnPropertyChanged("CountryResidence");
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With