3

大規模なデータ モデルを使用してアプリケーションを作成しています。その一環として、MVVM パターンを初めて使用しています。さまざまなエンティティを管理するための画面がたくさんあるため、多くのビュー モデルがあります。各ビュー モデルは、依存関係プロパティで作業している POCO エンティティのすべてのプロパティをラップしているため、それをエディター フィールドにバインドし、ユーザーが変更をコミットした場合にエンティティに書き戻すことができます。これは私にとって膨大な量の余分な足の仕事のように感じます.私は要点を逃したのか、それとも私の目標を達成するためのより簡単な方法があるのか​​ 疑問に思わずにはいられません. 例として、次のような Address View Model があります。

public class AddressViewModel : EntityViewModel<Address>
{
    #region Properties

    public string AddressLine1
    {
        get { return (string) GetValue(AddressLine1Property); }
        set { SetValue(AddressLine1Property, value); }
    }

    // Using a DependencyProperty as the backing store for AddressLine1.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AddressLine1Property =
        DependencyProperty.Register("AddressLine1", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty, HandleAddressChange));

    private static void HandleAddressChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var vm = d as AddressViewModel;
        if (vm != null)
        {
            vm.OnPropertyChanged(AddressAsSingleLineStringPropertyName);
        }
    }

    public string AddressLine2
    {
        get { return (string) GetValue(AddressLine2Property); }
        set { SetValue(AddressLine2Property, value); }
    }

    // Using a DependencyProperty as the backing store for AddressLine2.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AddressLine2Property =
        DependencyProperty.Register("AddressLine2", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));

    public string AddressLine3
    {
        get { return (string) GetValue(AddressLine3Property); }
        set { SetValue(AddressLine3Property, value); }
    }

    // Using a DependencyProperty as the backing store for AddressLine2.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AddressLine3Property =
        DependencyProperty.Register("AddressLine3", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));

    public string AddressLine4
    {
        get { return (string) GetValue(AddressLine4Property); }
        set { SetValue(AddressLine4Property, value); }
    }

    // Using a DependencyProperty as the backing store for AddressLine2.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AddressLine4Property =
        DependencyProperty.Register("AddressLine4", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));

    public string AddressLine5
    {
        get { return (string) GetValue(AddressLine5Property); }
        set { SetValue(AddressLine5Property, value); }
    }

    // Using a DependencyProperty as the backing store for AddressLine2.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AddressLine5Property =
        DependencyProperty.Register("AddressLine5", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));

    public string PostCode
    {
        get { return (string) GetValue(PostCodeProperty); }
        set { SetValue(PostCodeProperty, value); }
    }

    // Using a DependencyProperty as the backing store for PostCode.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PostCodeProperty =
        DependencyProperty.Register("PostCode", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty, HandleAddressChange));

    /// <summary>
    ///   Gets a value indicating whether this instance is valid for save.
    /// </summary>
    /// <value> <c>true</c> if this instance is valid for save; otherwise, <c>false</c> . </value>
    /// <exception cref="System.NotImplementedException"></exception>
    public override bool IsValidForSave
    {
        get { return !string.IsNullOrWhiteSpace(AddressLine1); }
    }


    /// <summary>
    ///   Gets a value indicating whether this instance is valid for edit.
    /// </summary>
    /// <value> <c>true</c> if this instance is valid for edit; otherwise, <c>false</c> . </value>
    public override bool IsValidForEdit
    {
        get { return true; }
    }



    #endregion

    #region Constructor

    /// <summary>
    /// Initializes a new instance of the <see cref="AddressViewModel" /> class.
    /// </summary>
    public AddressViewModel(Address address) : base(address)
    {
    }

    #endregion

    #region Private Methods

    /// <summary>
    ///   Sets the properties from entity.
    /// </summary>
    public override void SetPropertiesFromEntity()
    {
        AddressLine1 = Entity.AddressLine1;
        AddressLine2 = Entity.AddressLine2;
        AddressLine3 = Entity.AddressLine3;
        AddressLine4 = Entity.AddressLine4;
        AddressLine5 = Entity.AddressLine5;
        PostCode = Entity.PostCode;
    }

    /// <summary>
    ///   Sets the entity from properties.
    /// </summary>
    public override void SetEntityFromProperties()
    {
        Entity.AddressLine1 = AddressLine1;
        Entity.AddressLine2 = AddressLine2;
        Entity.AddressLine3 = AddressLine3;
        Entity.AddressLine4 = AddressLine4;
        Entity.AddressLine5 = AddressLine5;
        Entity.PostCode = PostCode;
    }
}

これは、単純な 5 つのプロパティ エンティティのラッピングです。

これを、モデル用のエディターを生成するだけの MVC Web アプリの作業と比較すると、大量のテキスト ボックスを双方向バインドできるように、オーバーヘッドにかなりの違いがあります。私は誰かが私が要点を逃し、これをすべて完全に間違っていると言って喜んでいますが、私のエンティティが私のモデルであることがわかる限り、ビューモデルはそれをラップし、ビューはビューモデルにバインドします。私は MVVM フレームワークを見てきましたが、ビューモデルを作成する労力を軽減するよりも、プログラム フローの制御を支援し、ビューとビュー モデルのコレクションを管理することに重点を置いているようです。

4

3 に答える 3

9

これらの DependencyProperties はまったく必要ありません。標準プロパティとして実装することをお勧めします。

UI の表示中にビューモデルが変更される可能性が高く、その変更を UI に反映させたい場合は、INotifyPropertyChangedインターフェイスを実装する必要があります。Fody PropertyChangedライブラリ (Nuget から入手可能) を使用すると、これを最も簡単に行うことができます。これは、クラスに属性を追加するだけで、すべての作業を行います。

依存関係プロパティが実際に必要になるのは、そのプロパティの値が Xaml で設定されていて、 を使用して値を設定する場合のみですMarkupExtension(たとえば、Bindingまたはを使用x:Static)。あなたの場合、コントロールのプロパティにバインディングを適用しているので(私は推測していますTextbox.Text)、それTextBox.TextDependencyProperty.

于 2013-09-16T13:30:48.370 に答える
1

コードの肥大化を減らすための複数のオプションがあります。

  1. インターフェイスを実装しINotifyPropertyChangedます。その構文は、C# にとってより簡潔で「自然」です。

  2. コード生成を使用します。依存関係プロパティを使用する必要がある場合、通常は T4 に依存します。

    例として、添付された依存関係プロパティの T4コード ジェネレーターを次に示します。これにより、構文は次のように単純になります。

    "WINDOWPLACEMENT Placement": { for: "Window",
        default: "WINDOWPLACEMENT.Invalid", changed: 1,
        flags: "BindsTwoWayByDefault" }
    
于 2013-09-16T13:32:11.357 に答える