How to automate the creation of WPF Viewmodel prop

2019-07-07 16:57发布

I am using Visual Studio '17 and Resharper in a WPF project that displays a lot of information to the user. Therefore I have a lot of properties that look like the following.

private double _foo;
public double Foo
{
   get { return _foo; }
   set { SetProperty(ref _foo, value); }
}

I'm looking for a quick automated way to create this. Right now I type 'prop' and get this

public double Foo {get; set;}

hit 'Alt-Enter' -> 'To property with backing field' to get this

private double _foo;
public double Foo
{
   get { return _foo; }
   set { _foo = value); }
}

and then manually type in the SetProperty(ref and ',' to get the final result. I've tried setting up snippets and resharper Templates but can't seem to figure out how to do it in one operation. What have people come up with to make this easier? Specifically, it would help tremendously if I could change an already existing auto-property to a View Model property.

4条回答
等我变得足够好
2楼-- · 2019-07-07 17:30

With my Visual Commander extension, you can use the following C# command (References: Microsoft.VisualBasic) to create a view model property:

public class C : VisualCommanderExt.ICommand
{
    public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
    {
        string propertyName = Microsoft.VisualBasic.Interaction.InputBox("Property name", "Create view model property [1/2]", "Foo", -1, -1);
        string propertyType = Microsoft.VisualBasic.Interaction.InputBox("Property type", "Create view model property [2/2]", "double", -1, -1);
        string fieldName = "_" + System.Char.ToLower(propertyName[0]) + propertyName.Substring(1);
        string snippet = @"
private {1} {2};
public {1} {0}
{{
   get {{ return {2}; }}
   set {{ SetProperty(ref {2}, value); }}
}}
";
        EnvDTE.TextSelection ts = DTE.ActiveDocument.Selection as EnvDTE.TextSelection;
        ts.Text = string.Format(snippet, propertyName, propertyType, fieldName);
    }
}

With C# 6 it is simpler, but requires Visual Commander Professional:

public class C : VisualCommanderExt.ICommand
{
    public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
    {
        string propertyName = Microsoft.VisualBasic.Interaction.InputBox("Property name", "Create view model property [1/2]", "Foo", -1, -1);
        string propertyType = Microsoft.VisualBasic.Interaction.InputBox("Property type", "Create view model property [2/2]", "double", -1, -1);
        string fieldName = "_" + System.Char.ToLower(propertyName[0]) + propertyName.Substring(1);

        EnvDTE.TextSelection ts = DTE.ActiveDocument.Selection as EnvDTE.TextSelection;
        ts.Text = $@"
private {propertyType} {fieldName};
public {propertyType} {propertyName}
{{
   get {{ return {fieldName}; }}
   set {{ SetProperty(ref {fieldName}, value); }}
}}
";
    }
}
查看更多
何必那么认真
3楼-- · 2019-07-07 17:32

You can define your own code snippet, to suit your needs precisely.

Here's one I wrote for myself, to generate property implementations compatible with the INotifyPropertyChanged base class implementation I also use regularly:

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>INPCProperty</Title>
      <Author>Peter Duniho</Author>
      <Description>Property declaration for NotifyPropertyChangedBase</Description>
      <Shortcut>inpcprop</Shortcut>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>fieldName</ID>
          <Default>_fieldName</Default>
          <ToolTip>Enter actual field name here</ToolTip>
        </Literal>
        <Literal>
          <ID>fieldType</ID>
          <Default>object</Default>
          <ToolTip>Enter actual field value type here</ToolTip>
        </Literal>
      </Declarations>
      <Code Language="CSharp">
        <![CDATA[private $fieldType$ $fieldName$;
        public $fieldType$ FieldName
        {
            get { return $fieldName$; }
            set { _UpdateField(ref $fieldName$, value); }
        }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Use the Visual Studio Snippet Manager to add the snippet to your installation.

(I didn't bother adding a field for the property name itself, because there didn't seem any point to it. But you can, of course, if you like. The only advantage I see vs. just selecting the property name and over-typing it is that if it's a field, you should be able to use the tab key to get directly to it before over-typing.)

查看更多
4楼-- · 2019-07-07 17:34

U can create your own snippet for that. I've create propbb snippet for BindableBase(from PRISM) property, it's essentialy same as you want. To create snippet here is video i've followed.

https://www.youtube.com/watch?v=tGmXlUFMTpk

and my snippet looks like this

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>propbb</Title>
      <Shortcut>propbb</Shortcut>
      <Description>Code snippet for BindableBase property and backing field</Description>
      <Author></Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>type</ID>
          <ToolTip>Property type</ToolTip>
          <Default>int</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 { SetProperty(ref $field$ , value);}
                  }
    $end$]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

if you want this is my snippet, just include it in your visual studio(like in video i've provided)

propbb snippet download

Path to add snippet in VS2017: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC#\Snippets\1033\Visual C# Just download snippet from my dropbox and copy there, to use it write propbb and tab tab

查看更多
祖国的老花朵
5楼-- · 2019-07-07 17:47

Install the Prism Template Pack from the Visual Studio Marketplace and then use the "propp" snippet.

https://marketplace.visualstudio.com/items?itemName=BrianLagunas.PrismTemplatePack

查看更多
登录 后发表回答