2017-06-01 45 views
0

我有一個關於的ViewModels的序列化和反序列化的問題 - 創建視圖模型的實例,並將其分配給視圖的DataContext的。我有一個列表保存ViewModel中的對象,我需要序列化然後反序列化。序列化視圖的反序列化和模型

關於反序列化,列表的大小不斷增長,不知道這裏發生了什麼。不是ViewModel只是另一個類的實例嗎?

例如我從一個類的2個對象開始。我對它進行序列化和反序列化,最後得到4條記錄,大小不斷增長。

我爲此做了一個測試場景。我正在使用JSON串行器。

// ---查看型號--- //

using System; 
using System.Windows; 
using System.Windows.Input; 
using Newtonsoft.Json; 

namespace JsonTest 
{ 
/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     CarVM = new CarViewModel(); //Create instance if View Model and assign it to the datacontext 
     this.DataContext = CarVM; 

    } 

    private CarViewModel CarVM { get; set; } 


    /// <summary> 
    /// Serialize 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void Serialize_Click(object sender, RoutedEventArgs e) 
    { 
     //Serialize and write to file 
     using (var fileStream = new FileStream(@"Config123.cfg", FileMode.Create)) 
     using (var streamWriter = new StreamWriter(fileStream)) 
     using (var jsonWriter = new JsonTextWriter(streamWriter)) 
     { 
      JsonSerializer ser = new JsonSerializer(); 
      ser.Formatting = Newtonsoft.Json.Formatting.Indented; //Format the output 
      ser.TypeNameHandling = TypeNameHandling.Auto; 
      ser.Serialize(jsonWriter, CarVM); //Serailizing View Model objects 
      jsonWriter.Flush(); 
     } 

     printData(); 
    } 

    /// <summary> 
    /// Deserialize 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void Deserialize_Click(object sender, RoutedEventArgs e) 
    { 
     using (var fileStream = new FileStream(@"Config123.cfg", FileMode.Open)) 
     using (var streamReader = new StreamReader(fileStream)) 
     using (var jsonReader = new JsonTextReader(streamReader)) 
     { 
      JsonSerializer ser = new JsonSerializer(); 
      ser.Formatting = Newtonsoft.Json.Formatting.Indented; 
      ser.TypeNameHandling = TypeNameHandling.Auto; 
      CarVM = ser.Deserialize<CarViewModel>(jsonReader); //reload the ViewModel with new viewmodel obtained from serializing 
     } 
     Console.WriteLine("--Deserialization--"); 
     printData(); 
    } 

    /// <summary> 
    /// Print Data 
    /// </summary> 
    private void printData() 
    { 
     foreach(Car c in CarVM.Cars) 
     { 
      Console.WriteLine(c.make + " " + c.year); 
     } 
    } 
    } 
} 

// ---簡單的類--- //

namespace JsonTest 
{ 
class Car 
{ 
    public string make { get; set; } 
    public int year { get; set; } 

    public Car() { } 

    public Car(string make, int year) 
    { 
     this.make = make; 
     this.year = year; 
    } 
    } 
} 

// ---查看 - - //

<Window x:Class="JsonTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:JsonTest" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <Button Content="Serialize" Margin="50" BorderThickness="0" Click="Serialize_Click"/> 
     <Button Grid.Column="1" Content="Deserialize" Margin="50" BorderThickness="0" Click="Deserialize_Click"/> 
    </Grid> 
</Window> 

// ---輸出--- //

--Serialization-- 
DeLorean 1975 
Subaru 2018 
--Deserialization-- 
DeLorean 1975 
Subaru 2018 
DeLorean 1975 
Subaru 2018 
--Serialization-- 
DeLorean 1975 
Subaru 2018 
DeLorean 1975 
Subaru 2018 
--Deserialization-- 
DeLorean 1975 
Subaru 2018 
DeLorean 1975 
Subaru 2018 
DeLorean 1975 
Subaru 2018 

// --- CarViewModel --- //

class CarViewModel 
    { 
     public CarViewModel() 
     { 
      Cars = new List<Car>(); 
      Cars.Add(new Car("DeLorean", 1975)); 
      Cars.Add(new Car("Subaru", 2018)); 
     } 

     private List<Car> cars; 
     public List<Car> Cars 
     { 
      get { return cars; } 
      set { cars = value; } 
     } 
    } 
+0

也許'CarVM.Cars'使用靜態後臺字段。由於'CarsViewModel'正在展示您所問的行爲,請考慮共享該代碼。 –

+0

@Ed - 剛剛更新ViewModel代碼。 –

回答

2

在視圖模型構造,增加了兩個汽車。

public CarViewModel() 
    { 
     Cars = new List<Car>(); 
     Cars.Add(new Car("DeLorean", 1975)); 
     Cars.Add(new Car("Subaru", 2018)); 
    } 

當你序列化,它序列化兩輛車。

當你反序列化,解串器使用默認的構造函數的類的實例。默認的構造函數添加這兩輛車。然後解串器添加兩個在JSON中序列化的汽車。

這不是你想到的行爲。如果您要對它進行序列化和反序列化,請不要在視圖模型構造函數中添加測試數據。

public CarViewModel() 
{ 
    Cars = new List<Car>(); 
} 

添加在這裏 - 一次:

public MainWindow() 
{ 
    InitializeComponent(); 
    CarVM = new CarViewModel 
    { 
     Cars = { 
      new Car("DeLorean", 1975), 
      new Car("Subaru", 2018) 
     }; 
    } 

    this.DataContext = CarVM; 
} 

此外,不要爲一個視圖模型使用List<T>。使用ObservableCollection<T>。當您添加或刪除項目時,它會通知UI中的任何綁定收集控件。您應該在您的視圖模型中實現INotifyPropertyChanged以及對屬性的更改也會導致通知UI。

+0

感謝您的回答和解釋。現在有道理。我在實際的ViewModel Code中使用'ObservableCollection '和'INotifyPropertychanged',有點複雜。儘管如此,我並沒有將它用於測試場景。謝謝。 –

+0

@SanMor聽起來不錯。 –