在wpf中快速生成ViewModel属性?

Oli*_*ver 8 c# wpf mvvm

阅读本文后,我的PersonViewModel课程中有以下代码:

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我也有CountryDomiciled,CountryPassport并且LegalJurisdiction都有相同的格式.同样,我有很多String属性,所有属性都共享其格式.

这导致了许多相同的代码!但是,我无法弄清楚如何使这更简洁.

有没有更好的方法来生成这些属性,使其保持强类型?

Ser*_*kiy 10

我使用Visual Studio的代码片段,它为我生成支持存储和事件提升的属性.只需创建带有名称propchanged(或其他名称,如果您愿意)的xml文件以及以下内容:

<?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>
Run Code Online (Sandbox Code Playgroud)

并把它放到文件夹中C:\Users\YourName\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets\.

接下来,我从一些基础ViewModel继承我的ViewModel,它实现了INotifyPropertyChangedinteface并提供OnPropertyChanged了生成`PropertyChanged'事件的受保护方法.

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当您键入propchangedVisual Studio时,它将询问您的属性类型和名称,并为您生成代码.

public class PersonViewModel : ViewModel
{
    // type here 'propchanged' (or other shortcut assigned for snippet)
}
Run Code Online (Sandbox Code Playgroud)

更新:

另一种选择是通过像PostSharp这样的AOP框架生成代码.在这种情况下,代码将在编译期间生成并添加(因此您的类将保持干净).以下是通过PostSharp属性更改实现INotifyProperty的示例:

[Notify]
public class PersonViewModel
{
    public Jurisdiction CountryResidence { get; set; }
    public Jurisdiction CountryBirth { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于复杂的MSIL生成框架,摘要为+1。保持简单笨拙! (2认同)

Dan*_*zey 4

更新: NotifyPropertyWeaver 已弃用,并以PropertyChanged.Fody 的形式继续其生命。这绝对是解决这个问题的超级酷方法。这是一个仅编译时的解决方案。

这里有一些可以节省您代码和麻烦的东西:NotifyPropertyWeaver

使用上面的内容,您可以在没有任何INotifyPropertyChanged相关代码的情况下实现您的属性,并且构建步骤将为您处理连接。

这是一个简单的项目包含(也可以通过 Nuget 获得),它将自动将回调注入OnPropertyChanged到实现INotifyPropertyChanged. 它在编译时执行此操作(因此没有运行时命中),并且您的代码可以只具有自动实现的属性(除非您使用单独的支持对象)。

它甚至包括值相等性检查,因此它涵盖了完整的逻辑。我尚未使用手动实现的属性对其进行测试,但值得一试。

编辑:我现在已经测试了它,它工作正常:手动实现的属性将“正常工作”。