2016-07-11 27 views
2

私はMVVMを使用してWPFでアプリケーションを構築しています。さまざまなオブジェクトモデルのデータをXMLとして保存します。 Serialize an object to XMLを使用してオブジェクトをXMLに正しくシリアル化できますが、問題はMVVM自体にあります。
ViewModelコードのICommandセグメント内にあるオブジェクトのModelに直接アクセスすることはできません(E.G. Saveを押すと、ViewModel内のICommandメソッドに移動します)。
私はモデルをシリアライズ可能なものにしました。「Unexpected type」が戻ってこない場合でも、Serializeメソッド(これは独自の静的ヘルパークラスに含まれています)に直接渡す方法はありません。私は(VieWModelはシリアライズ可能ではないため)、Modelクラスだけでなく、余分なゴミがたくさん残ってしまいます。WPFのオブジェクトをXMLにシリアル化する

私はこれを間違って設計しているのか、それとももっと良い方法があるのか​​わかりません。

P.S.これらのフィールドはすべて、適切にバインドされたTextBoxコントロールに書き込まれています。今、私は、他のデータ型がうまくいかないような問題を避けるために、名前フィールドを実行しようとしています。

EDIT:コメントで要求されているように、今の目標はいくつかのテキストボックス(最初、真ん中、姓)にテキストの一部を書き込んでからXMLファイルに保存することです。問題の

namespace XMLaw.Model 
{ 
    [Serializable] 
    public class ClientModel 
    { 
     private string firstName { get; set; } 
     private string middleName { get; set; } 
     private string lastName { get; set; } 
     private DateTime dateOfBirth { get; set; } 
     private string ssn { get; set; } //Format: AA ## ## ## A, spaces optional 
     private string address { get; set; } 
     private string phone { get; set; } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(string propertyName) 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     #region Name Properties 
     public string FirstName 
     { 
      get { return firstName; } 
      set 
      { 
       if(firstName != value) 
       { 
        firstName = value; 
        OnPropertyChanged("FirstName"); 
       } 
      } 
     } 
     public string MiddleName 
     { 
      get { return middleName; } 
      set 
      { 
       if (middleName != value) 
       { 
        middleName = value; 
        OnPropertyChanged("MiddleName"); 
       } 
      } 
     } 
     public string LastName 
     { 
      get { return lastName; } 
      set 
      { 
       if (lastName != value) 
       { 
        lastName = value; 
        OnPropertyChanged("LastName"); 
       } 
      } 
     } 
     #endregion 

     public DateTime DateOfBirth 
     { 
      get { return dateOfBirth; } 
      set 
      { 
       if (dateOfBirth != value) 
       { 
        DateTime dt = Convert.ToDateTime(value); //This will probably need to revisited since DateTime objects are fucking stupid 
        dateOfBirth = dt.Date; 
        OnPropertyChanged("DateOfBirth"); 
       } 
      } 
     } 

     public string SSN 
     { 
      get { return ssn; } 
      set 
      { 
       if(ssn != value) 
       { 
        ssn = value; 
        OnPropertyChanged("SSN"); 
       } 
      } 
     } 

     public string Address 
     { 
      get { return address; } 
      set 
      { 
       if(address != value) 
       { 
        address = value; 
        OnPropertyChanged("Address"); 
       } 
      } 
     } 

     public string Phone 
     { 
      get { return phone; } 
      set 
      { 
       if(phone != value) 
       { 
        phone = value; 
        OnPropertyChanged("Phone"); 
       } 
      } 
     } 

    } 
} 

とViewModelに(シリアル化を呼び出すSaveコマンドは一番下にある)

namespace XMLaw.ViewModel 
{ 
    public class ClientViewModel : INotifyPropertyChanged 
    { 
     private ClientModel client; 
     private string displayMessage; 
     private ICommand btnSave; 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void OnPropertyChanged(string propertyName) 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     public ClientViewModel() 
     { 
      client = new ClientModel(); 
     } 

     public ClientModel ClientModel 
     { 
      get { return client; } 
     } 

     public string DisplayMessage 
     { 
      get { return displayMessage; } 
      set 
      { 
       if(displayMessage != value) 
       { 
        displayMessage = value; 
        OnPropertyChanged("DisplayMessage"); 
       } 
      } 
     } 

     public ICommand SaveCommand 
     { 
      get 
      { 
       if (btnSave == null) 
        btnSave = new Save(); 
       return btnSave; 
      } 
      set { btnSave = value; } 
     } 

     protected class Save : ICommand 
     { 

      public bool CanExecute(object param) { return true; } 
      public event EventHandler CanExecuteChanged; //Compiler yells at you if you don't implement this from inhereted ICommand 
      public void Execute(object param) 
      { 
       ClientViewModel viewModel = (ClientViewModel)param; 
       //TODO: Insert XML serialization and save to a file 
       var xml = Helper.Serialize(param); 


       //Placeholder to make sure the button works 
       viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now; 
      } 
     } 


    } 
} 

そして、私は臆面もなくから取ったSerailization方法:問題のモデルを要約

上記のリンク

public static class Helper 
{ 
    public static string Serialize<T>(this T value) 
    { 
     if (value == null) 
     { 
      return string.Empty; 
     } 
     try 
     { 
      var xmlserializer = new XmlSerializer(typeof(T)); 
      var stringWriter = new StringWriter(); 
      using (var writer = XmlWriter.Create(stringWriter)) 
      { 
       xmlserializer.Serialize(writer, value); 
       return stringWriter.ToString(); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new Exception("An error occurred", ex); 
     } 
    } 
} 
+2

いけないバッキングとしてプロパティを使用'Properties'のフィールド(あなたは本当にそれをしましたか?)プライベートな 'Properties'フィールドを作ってください。さらに、 'PropertyChanged'イベントを直列化することはできません。 – lokusking

+0

「プロパティのバッキングフィールドとしてプロパティを使用しないでください」という意味の例を教えてください。これは実際にMVVMを使用するための最初の試みであり、私は畳み込まれていないチュートリアルを見つけるのに大変時間がかかりました。これが私が見つけた唯一のコヒーレントな方法でした。 –

+1

@KoalaBearここで 'private string firstName {get;セット; } '? '{get;セット; } 'セミコロンで'プライベート文字列firstName; 'それは、プロパティをフィールドに変えます。プロパティにはアクセサの取得/設定があります。フィールドはメンバ変数に過ぎません。 –

答えて

3

クライアントモデルをこれに変更してください:

[Serializable] 
    public class ClientModel 
    { 
     private string firstName; 
     private string middleName; 
     private string lastName; 
     private DateTime dateOfBirth; 
     private string ssn; 
     private string address; 
     private string phone; 


     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(string propertyName) 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     #region Name Properties 
     public string FirstName { 
      get { return firstName; } 
      set { 
       if (firstName != value) 
       { 
        firstName = value; 
        OnPropertyChanged("FirstName"); 
       } 
      } 
     } 
     public string MiddleName { 
      get { return middleName; } 
      set { 
       if (middleName != value) 
       { 
        middleName = value; 
        OnPropertyChanged("MiddleName"); 
       } 
      } 
     } 
     public string LastName { 
      get { return lastName; } 
      set { 
       if (lastName != value) 
       { 
        lastName = value; 
        OnPropertyChanged("LastName"); 
       } 
      } 
     } 
     #endregion 

     public DateTime DateOfBirth { 
      get { return dateOfBirth; } 
      set { 
       if (dateOfBirth != value) 
       { 
        DateTime dt = Convert.ToDateTime(value); //This will probably need to revisited since DateTime objects are fucking stupid 
        dateOfBirth = dt.Date; 
        OnPropertyChanged("DateOfBirth"); 
       } 
      } 
     } 

     public string SSN { 
      get { return ssn; } 
      set { 
       if (ssn != value) 
       { 
        ssn = value; 
        OnPropertyChanged("SSN"); 
       } 
      } 
     } 

     public string Address { 
      get { return address; } 
      set { 
       if (address != value) 
       { 
        address = value; 
        OnPropertyChanged("Address"); 
       } 
      } 
     } 

     public string Phone { 
      get { return phone; } 
      set { 
       if (phone != value) 
       { 
        phone = value; 
        OnPropertyChanged("Phone"); 
       } 
      } 
     } 

    } 

使用法:

var xx = new ClientModel(); 
      xx.FirstName = "John"; 
      xx.LastName = "Smith"; 
      xx.DateOfBirth = DateTime.Now; 

      var result = xx.Serialize(); 

結果:

ます。http://www.w3.org/2001/XMLSchema-instance \ " のxmlns:のxsd = \" http://www.w3.org/2001/XMLSchema\ " > John Smith 2016-07-11T00:00:00 + 02:00

EDIT:

このコード:

public void Execute(object param) 
      { 
       ClientViewModel viewModel = (ClientViewModel)param; 
       //TODO: Insert XML serialization and save to a file 
       var xml = Helper.Serialize(param); 


       //Placeholder to make sure the button works 
       viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now; 
      } 

この置き換えてください:

public void Execute(object param) 
      { 
       ClientModel model= (ClientModel)param; 
       //TODO: Insert XML serialization and save to a file 
       var xml = Helper.Serialize(param); 


       //Placeholder to make sure the button works 
       viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now; 
      } 

は確認してください、あなたのParamはタイプClientModelです。

また、私は非常にhow DataBinding works

編集2(コマンドThingyの)の基本に入るために、あなたをお勧めします。

class Save : ICommand 
    { 
     public ClientModel Model { get; set; } 
     public bool CanExecute(object param) { return true; } 
     public event EventHandler CanExecuteChanged; //Compiler yells at you if you don't implement this from inhereted ICommand 
     public void Execute(object param) 
     { 
      //TODO: Insert XML serialization and save to a file 
      var xml = Helper.Serialize(this.Model); 


      //Placeholder to make sure the button works 
      viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now; 
     } 
    } 

使用法:

public ICommand SaveCommand 
     { 
      get 
      { 
       if (btnSave == null) 
        btnSave = new Save(); 
btnSave.Model = this.ClientModel; 

       return btnSave; 
      } 
      set { btnSave = value; } 
     } 
+0

ああ、はい。私は今、私がどれほど馬鹿なのかを見ます。しかし、ViewModelクラスの "save"コマンドの中からオブジェクトを直列化できないという問題は解決しません。 –

+0

投稿編集: 'XMLaw.ViewModel.ClientViewModel'タイプのオブジェクトをキャストして 'XMLaw.Model.ClientModel'と入力できません。 –

+1

最初の手順:[RelayCommand](http://www.c-sharpcorner.com/UploadFile/20c06b/icommand-and-relaycommand-in-wpf/)を使用します。代わりに、あなたの 'Save'-Commandに' ClientModel '型のプロパティを実装し、これをあなたの目的に使うように設定してください。 – lokusking

関連する問題