8

この記事を読んだ後、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");
        }
    }
}

CountryDomiciledCountryPassportおよびもありLegalJurisdiction、すべて同じ形式です。同様に、多くのStringプロパティがあり、そのすべてが形式を共有しています。

これにより、多くの同じコードが生成されます。ただし、これをより簡潔にする方法がわかりません。

強く型付けされたままにするこれらのプロパティを生成するより良い方法はありますか?

4

8 に答える 8

11

私は 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>

そしてそれをフォルダーに入れますC:\Users\YourName\Documents\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets\

次に、インターフェイスを実装し、 「PropertyChanged」イベントを生成するためのINotifyPropertyChanged保護されたメソッドを提供する、いくつかの基本 ViewModel から ViewModel を継承します。OnPropertyChanged

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

Visual Studio に入力propchangedすると、プロパティの種類と名前を尋ねられ、コードが生成されます。

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

アップデート:

別のオプションは、PostSharpのような AOP フレームワークによってコードを生成することです。この場合、コンパイル中にコードが生成および追加されます (したがって、クラスはクリーンなままになります)。PostSharp属性によって変更された INotifyProperty を実装する例を次に示します。

[Notify]
public class PersonViewModel
{
    public Jurisdiction CountryResidence { get; set; }
    public Jurisdiction CountryBirth { get; set; }
}
于 2012-04-16T13:22:55.877 に答える
4

更新: NotifyPropertyWeaverは非推奨になり、 PropertyChanged.Fodyとして存続します。これは、この問題を解決するための絶対的な超クールな方法です。これはコンパイル時のみのソリューションです。

コードとトラブルを節約するものがあります:NotifyPropertyWeaver

上記を使用すると、関連するコードなしでプロパティを実装できINotifyPropertyChanged、ビルドステップで配線が処理されます。

OnPropertyChangedこれは、を実装するクラスのプロパティにコールバックを自動的に挿入する単純なプロジェクトインクルード(Nugetからも利用可能)ですINotifyPropertyChanged。コンパイル時に実行され(実行時のヒットがないため)、コードは自動実装されたプロパティを持つことができます(別のバッキングオブジェクトを使用している場合を除く)。

値の同等性チェックも含まれているため、完全なロジックをカバーしています。手動で実装したプロパティでテストしたことはありませんが、チェックする価値があります。

編集:私は今それをテストしました、そしてそれはうまくいきます:手動で実装されたプロパティは「うまくいく」でしょう。

于 2012-04-16T13:32:30.607 に答える
2

本当に探しているものではありませんが、余談ですが、ロジック テストを逆にすることで、プロパティごとに 2 行を節約できます。

public Jurisdiction CountryResidence
{
    get
    {
        return Model.CountryResidence;
    }
    set
    {
        if (Model.CountryResidence != value)
        {
            Model.CountryResidence = value;
            base.OnPropertyChanged("CountryResidence");
        }
    }
}
于 2012-04-16T13:14:47.420 に答える
1

プロパティ名(リファクタリングを有効にするために必要)への「強い型の」参照を取得するには、式を使用できます。次のメソッドを、おそらくビューモデルの基本クラスに配置します。

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));
}

ビューモデルでは、次のことができるようになります。

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

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

これで、参照が実際のプロパティに対して行われるため、リファクタリングプロパティ名が自動的に取得されます。

これにより、プロパティ名のハードコーディングの問題点が解決されますが、それでも4〜5行の定型コードが必要です。notifypropertyweaverPostSharpのようなアスペクト指向のアプローチは、ビューモデルのすべての手動コーディングを実際に削除します。

于 2012-04-16T14:50:38.333 に答える
1

XAML PowerToysを試して、ViewModel をすばやく生成してください。

于 2012-04-16T13:19:07.123 に答える
1

組み込みの方法はわかりませんが、コードを生成するマクロを記録できます。これを行う最も簡単な方法は、マクロの記録を開始してから、キーボードのみを使用して必要なものを作成することです (便利なキーボード ショートカットのリストはこちらにあります) 。

たとえば、プロパティのパブリック バージョンを生成するものがあるので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}" />
于 2012-04-16T13:14:44.557 に答える
0

この目的のために、小さな T4 テンプレートを作成しました。

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

于 2014-08-12T12:49:39.333 に答える
0

またはなどの Visual Studio コード スニペットを使用してみませんでしたproppropfull? 入力してTabキーを2回押すだけです。問題は、スニペットがPropertyChangedイベントを発生さpropfullせないことです。

しかし実際には、そのようなタスクにはサードパーティのスニペットが必要です。これが私が見つけたものです:INPCを使用したプロパティスニペット

于 2012-04-16T13:11:36.147 に答える