私は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);
}
}
}
いけないバッキングとしてプロパティを使用'Properties'のフィールド(あなたは本当にそれをしましたか?)プライベートな 'Properties'フィールドを作ってください。さらに、 'PropertyChanged'イベントを直列化することはできません。 – lokusking
「プロパティのバッキングフィールドとしてプロパティを使用しないでください」という意味の例を教えてください。これは実際にMVVMを使用するための最初の試みであり、私は畳み込まれていないチュートリアルを見つけるのに大変時間がかかりました。これが私が見つけた唯一のコヒーレントな方法でした。 –
@KoalaBearここで 'private string firstName {get;セット; } '? '{get;セット; } 'セミコロンで'プライベート文字列firstName; 'それは、プロパティをフィールドに変えます。プロパティにはアクセサの取得/設定があります。フィールドはメンバ変数に過ぎません。 –