快速生成视图模型的属性在WPF?(Quickly generating ViewModel prop

2019-07-29 00:29发布

看完这篇文章 ,一个在我下面的代码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");
        }
    }
}

我也有CountryDomiciledCountryPassportLegalJurisdiction ,都具有相同的格式。 同样,我有很多的String特性,所有这些都分享他们的格式。

这导致大量的单调枯燥的代码! 不过,我不知道如何使这个更简洁。

有没有更好的方法来生成这些性质使他们强类型?

Answer 1:

UPDATE:NotifyPropertyWeaver已被弃用,并继续为生命PropertyChanged.Fody 。 这是解决这个问题的绝对超爽的方式。 这是一个编译时唯一的解决办法。

这里的东西,将节省您的代码和麻烦: NotifyPropertyWeaver

使用上面,你可以在没有任何实现你的属性INotifyPropertyChanged相关代码和生成步骤将处理接线,为您服务。

这是一个简单的项目包括(也可以通过提供的NuGet),将自动注入OnPropertyChanged的回调实现任何类的属性INotifyPropertyChanged 。 它是在编译时(因此没有运行时命中)和你的代码可以只具有自动实现的属性(除非你的情况,你使用一个单独的支持对象在哪里)。

它甚至还包括了价值平等的检查,所以它涵盖了完整的逻辑。 我还没有手动实现性能测试,但值得一试。

编辑:我现在已经测试了它,它工作得很好:“只是工作”手动实现的属性会



Answer 2:

我使用的代码段为Visual Studio,这与后备存储和事件提高了我产生财产。 只需创建名称为xml文件propchanged (或其他名称,如果你愿意的话)和以下内容:

<?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>

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

接下来,我继承了一些基本的视图模型,它实现了我的ViewModels INotifyPropertyChanged inteface和提供保护的方法OnPropertyChanged产生`的PropertyChanged”事件。

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
    }
}

现在当你输入propchanged在Visual Studio中,它会问你的属性类型和名称,并为你生成代码。

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

更新:

另一种选择是由像AOP框架生成代码PostSharp 。 在这种情况下,代码生成和编译过程中添加(因此你的类将保持干净)。 这里是例如实现INotifyProperty改变经由PostSharp属性的:

[Notify]
public class PersonViewModel
{
    public Jurisdiction CountryResidence { get; set; }
    public Jurisdiction CountryBirth { get; set; }
}


Answer 3:

不是真的你正在寻找的东西,但作为一个预留您可以通过扭转你的逻辑测试节省每财产两行:

public Jurisdiction CountryResidence
{
    get
    {
        return Model.CountryResidence;
    }
    set
    {
        if (Model.CountryResidence != value)
        {
            Model.CountryResidence = value;
            base.OnPropertyChanged("CountryResidence");
        }
    }
}


Answer 4:

我不知道任何内置的方式,但你可以录制宏,将生成的代码为您服务。 我觉得这样做是刚开始录制宏,然后再创建任何你想要使用键盘只(你可以找到得心应手的键盘快捷键列表,最简单的方法在这里 )

例如,我有一个生成的属性的公版,所以我必须键入是private string _someValue; 和打我的宏,它会产生与属性更改通知沿着公共财产。

这就是说,要记住,这是在MVVM完全有效的整个模型暴露给视图为了简单和方便起见。 因此,而不是分别暴露出每一型号的特性,您只需为您的模型对象的一个​​属性。

public Model SomeModel
{
    get
    {
        return Model;
    }
    set
    {
        if (Model == value)
            return;
        else
        {
            Model= value;
            base.OnPropertyChanged("SomeModel");
        }
    }
}

并绑定到这样的模型的属性:

<TextBox Text="{Binding SomeModel.SomeProperty}" />


Answer 5:

请尝试XAML PowerToys的快速生成的ViewModels;



Answer 6:

为了得到一个“强类型的”参考属性名称(这是为了使重构),您可以使用表达式。 将下面的方法,也许在你的ViewModels基类:

protected void RaisePropertyChanged<T>(Expression<Func<T>> property)
{
    var handler = PropertyChanged;
    if (handler == null) return;

    var propertyName = NotifyPropertyChangedHelper.GetPropertyNameFromExpression(property);
    handler(sender, new PropertyChangedEventArgs(propertyName));
}

在你的ViewModels,然后您就能够做到以下几点:

public Jurisdiction CountryResidence
{
    get { return Model.CountryResidence; }
    set 
    {         
        if (Model.CountryResidence == value)
            return;

        Model.CountryResidence = value;
        OnPropertyChanged(() => CountryResidence);
    }
}

现在,由于基准是针对实际的属性重构属性名被自动拾取。

这解决了硬编码的属性名称的痛点,虽然它仍然需要4-5行的样板代码。 像面向方面的办法notifypropertyweaver和PostSharp真正消除在所有的ViewModels手工编码。



Answer 7:

你有没有尝试过使用Visual Studio代码片段,如proppropfull ? 只需键入它,然后按Tab键两次。 问题是propfull片段不会引发PropertyChanged事件。

但实际上应该有这样的任务第三方片段。 这里是我的发现: 财产片段与INPC



Answer 8:

我写了一个小T4模板用于这一目的。

http://software.the-architect.info/2014/08/12/a-quick-way-to-generate-view-model-properties-in-wpf



文章来源: Quickly generating ViewModel properties in wpf?
标签: c# wpf mvvm