Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quickly generating ViewModel properties in wpf?

Tags:

c#

mvvm

wpf

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?

like image 386
Oliver Avatar asked Apr 16 '12 12:04

Oliver


3 Answers

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; }
}
like image 167
Sergey Berezovskiy Avatar answered Sep 18 '22 12:09

Sergey Berezovskiy


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."

like image 28
Dan Puzey Avatar answered Sep 21 '22 12:09

Dan Puzey


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");
        }
    }
}
like image 32
GazTheDestroyer Avatar answered Sep 21 '22 12:09

GazTheDestroyer