2011-09-28 7 views
2

私のWPFアプリケーションでは、データをフェッチするためにWCFサービスを使用します。 当然ながら、ある時点で私はDataContractをWPFアプリケーション全体に渡す必要がある「複雑な」オブジェクトを持っていました。観測可能なデータコントラクトと双方向バインディング

もちろん、私は変更に対応する必要があります。私はViewModelsにINotifyPropertyChangedを実装しますが、実際には一部のオブジェクトは実際にはDataContractsなので、INotifyPropertyChangedを実装するように再構成する必要があります。

私はそれが乱雑であるように感じます。

私がしようとしたのは、DataContract定義にインターフェイスを直接実装することですが、変更に適切に対応することはできません。
たとえば、双方向データ・バインドTextBoxのテキストが変更されている場合、対応するSQL表の値をWCFサービスを介して変更することによってViewModelが対応する必要がありますが、オブジェクトはWCF側で定義されているため、プロパティの設定者でそれを行うことはできません。

私が今行っているのは、DataContractsのPropertyChangedイベントを購読し、リフレクションを使用して、変更されたプロパティとその新しい値を知ることです。
しかし、これらのオブジェクトはObservableCollection<T>に保持されています。これは多くのイベントですが、非常に脆いと感じています...たとえば、コレクションから要素を追加/削除するとどうなりますか?

私は、この(これが悪いと思う)のようにそれを実行します。

foreach (ImageInfo imgi in (param.Images as ObservableCollection<ImageInfo>)) 
{ 
    imgi.PropertyChanged += (sender, args) => 
     { 
      object newValue = Tools.GetProperty((sender as ImageInfo), args.PropertyName); 
     }; 
} 

そして私は、WCFサービスにそれを送り返すと思います。

もっと洗練されたソリューションがありますか? ViewModelにのみINotifyPropertyChangedを実装し、代わりにDataContractsを再構成する必要がありますか?

ありがとうございます!

+1

私はこれをどのように説明することができます。データコントラクトは単純なオブジェクトです。ビューモデルは、コンストラクタパラメータとしてデータコントラクトを受け取り、それ自身のプロパティを記入します。ユーザーが保存ボタンをクリックすると、ビューモデルは新しい値を収集し、新しいデータコントラクトを作成してサービスに送信します。 – vorrtex

+0

はい、私は「保存」ボタンを持っていません。DBの変更を反映するために、プロパティが変更されるたびにサービスを呼び出す必要があります。 –

+0

これは難しく、データベースの作業量が増えます。しかし、もし私にそのような要求があったとしても、私は同じことをするでしょう:データ契約が一つの財産だけであっても、新しいデータ契約を作り、それをサービスに送ってください。 RaisePropertyChangedメソッドにメソッド呼び出しを追加する場合は、ライブ変更を処理できます。メインのビューモデル内でSaveメソッドを呼び出すか、子アイテムから何らかの種類のMessengerクラスを使用します。 – vorrtex

答えて

0

よしので、いくつかの時間が経過した後、それを通じ考えて、私は今のところ、このようにそれを実装しますが、私は(彼は私に良いアイデアを与える場合、私は更新します)次月曜日の専門家と会うので、それは変更される場合があります。

1)WCFサービスは、のDataContractなどがあります。

[DataContract] 
public class MyWcfData : INotifyPropertyChanged 
{ 
    public MyWcfData() 
    { 
     MyField = ""; 
    } 

    [DataMember] 
    public string MyField; 

    [DataMember] 
    public string MyFieldModified; 
} 

注: INotifyPropertyChangedのは、いつものように実装されて、私はちょうど読みやすさのためにそれを残して、私はこの上で私のスニペットを持っていけないので、コンピューター。

サービスでGetMyData()が呼び出されると、そのクラスのインスタンスが返され、 "MyField"だけが設定されます。 MyFieldModifiedはnullのままです。 MyWcfDataを受け取っている私のDAL(そのクライアント側)、オン

:ここ

public class MyDAL 
{ 
    //... some init code 
    public MyWcfData GetMyWcfData() 
    { 
     MyWcfData newData = m_WcfService.GetMyData(); 
     newData.MyFieldModified = newData.MyField; 
     return newData; 
    } 
} 

ポイントは、私は変更を追跡し、のみ更新できるように、データを複製する必要があるということですたとえユーザーがそれを10回変更したとしても(私はいつも元の値と比較する)しかし、私は有線を介して複製されたデータを送信したくないので、ビジネスオブジェクトがアクセスする前にDALで複製を行います。私の見解のViewModelにに

public class MyViewModel 
{ 
    //.. some init code 
      DelegateCommand<MyWcfData> _GetDataCommand; 
     public DelegateCommand<MyWcfData> GetDataCommand 
     { 
      get 
      { 
       if (_GetDataCommand == null) 
        _GetDataCommand = new DelegateCommand<MyWcfData>(GetData); 
       return _GetDataCommand; 
      } 
     }   
     public void GetData(MyWcfData param) 
     { 
      m_WcfData = m_DAL.GetMyWcfData(); 
     } 
} 

そして最後になりましたが、私のXAMLで、私はTextBoxで(双方向結合に)MyFieldModifiedに特異的に結合します。
TextChangedイベントでSystem.Windows.Interactivityを使用してDelegateCommandに電話をかけます。
最後のコマンドが実行されると、変更をキューに入れ(変更の順序を追跡するため)、ユーザーが[保存]ボタンを押したときにデータの永続性のためにWcfサービスに戻します。

注:私は変更の数を追跡しての結合を介してそれに応じて、保存ボタンを有効にすることができるように私が実際にカスタムメイドObservableQueue<T>を使用しています。私はそれがあまり機能しませんので、この場合には、それが働いていたにもかかわらず、それは瞬時に行われたすべての小さな変更を保存することをあきらめた:私はそうチューニング;-)

注2とどまるそれについてのブログ記事を行います使用されており、ほとんど変更が予定されていません。他の答えで指摘されているように、それは悪い習慣です。

1

WCFサーバーによってデータベースにリンクされているリアルタイムシステムが必要ですか?

Get/Setメソッドがデータベースに出入りするModelオブジェクトの作成についてはどうですか?

public class MyModel : INotifyPropertyChanged 
{ 
    private IMyModelService service; 
    public int Id { get; set; } 

    public MyModel (IMyModelService wcfService, int id) 
    { 
     this.Id = id; 

     this.service = wcfService; 
     AutoMapper.Map<MyModelDTO, MyModel>(service.GetMyModel(this.Id), this); 
    } 

    public int SomeValue 
    { 
     get 
     { 
      return service.GetSomeValue(this.Id); 
     } 
     set 
     { 
      service.SetSomeValue(this.Id, value); 
      RaisePropertyChanged("SomeValue"); 
     } 
    } 
} 

あなたは、キャッシュオブジェクトのプロパティ、ローカルにも可能性があり、複数の人が一つのオブジェクトを変更できるかどうかを警告するメッセージ・システムのいくつかの種類を必要とするかもしれませんが、おそらく、パフォーマンスが改善されるサービスは、非同期呼び出しをWCFを作ります別のユーザーがプロパティを更新すると、MyObjectのクライアントが変更されました。

クライアント上のViewModelは、WCFサービスではなく、モデルの作成を担当します。

public class LoadObject(int id) 
{ 
    CurrentObject = new MyModel(serviceReference, id); 
} 
+0

それは私が心に留めていたことですが、そのクラスをどのように構築するのか分かりません。オブジェクトは、ViewModelがデータを要求し、WCFオブジェクト(コントラクト)がINotifyPropertyChangedを実装するときに、WCFサービスによって作成されます。それは自分自身を呼び出すことはできません。上のコードが機能するには、合成が必要です。 –

+0

そのアプリは数十人のユーザーによって同時に使用されますが、WCFのデュプレックスはトピックにはありません(後で説明します)。 –

+0

@バブン私は実際にデータ転送オブジェクト(DTO)でWCFの作業を行い、 'AutoMapper'のようなものを使ってモデルにDTOをマップします。 ViewModelは実際にModelオブジェクトの作成を担当し、コンストラクタ内の現在のWCFサービスインスタンスに渡します。コンストラクタはWCFサービスを使用してサーバーからDTOを取得し、そのプロパティをマップします。私の編集を参照してください。 DTOを使用しなくても、ViewModelは依然としてオブジェクトの作成を担当する必要があるため、サービス参照に渡すことができます。 – Rachel

関連する問題