2016-10-14 31 views
0

我有一個帶有xml配置文件的wpf應用程序。WPF C#在綁定驗證過程中序列化爲XML

我做誰是綁定到一個MainWindow.xaml ViewModel類,而我正在使用IDataErrorInfo的和有效性規則類的一些驗證。

我想要的是,如果用戶更改了一個值,並且該值通過了驗證,則配置類將被序列化爲xml。

爲了節省我有一個類擴展:

public static class ConfiguracionExtension 
{ 
    public static void Save(this Configuration configXML) 
    { 
     string ConfigPath = AppDomain.CurrentDomain.BaseDirectory + "config.xml"; 
     XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
     XmlSerializer serializer = new XmlSerializer(typeof(Configuration)); 
     Stream writer = new FileStream(ConfigPath, FileMode.Create); 
     ns.Add("", ""); 
     serializer.Serialize(writer, configXML, ns); 
     writer.Close(); 
    } 
} 

的配置類的樣子:

[Serializable, XmlRoot("configuration")] 
public class Configuration : IDataErrorInfo, INotifyPropertyChanged 
{ 
    private int _minute; 
    [XmlElement] 
    public int minute 
    { 
     get 
     { 
      return _minute; 
     } 
     set 
     { 
      _minute = value; 
      OnPropertyChanged("minute"); 
     } 
    } 
    public static Configuration Load() 
    { 
     string ConfigPath= AppDomain.CurrentDomain.BaseDirectory + "config.xml"; 
     if (File.Exists(ConfigPath)) 
     { 
      try 
      { 
       XmlSerializer _s = new XmlSerializer(typeof(Configuration)); 
       return (Configuration)_s.Deserialize(new XmlTextReader(ConfigPath)); 
      } 
      catch (Exception ex) 
      { 
       Auxiliar.writeError(ex.ToString()); 
       return new Configuration(); 
      } 
     } 
     else 
      return new Configuration(); 
    } 
    public Configuracion() 
    { 
     minutes = 60; 
    } 
    #region IDataErrorInfo Members 
    public string Error 
    { 
     get { return String.Empty; } 
    } 

    public string this[string columnName] 
    { 
     get 
     { 
      String errorMessage = String.Empty; 
      switch (columnName) 
      { 
       case "minute": 
        if (minute < 1) 
        { 
         errorMessage = "minutes can't be less than 1"; 
        } 
        break; 
      } 
      return errorMessage; 
     } 
    } 
    #endregion 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(String propertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

和驗證規則如下:

public class MinutesValidation : ValidationRule 
{ 
    private int _min; 
    public int Minimum 
    { 
     get { return _min; } 
     set { _min = value; } 
    } 
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
    { 
     int minute; 
     Boolean noIllegalChars; 
     noIllegalChars = int.TryParse(value.ToString(), out minute); 

     if (value.ToString().Length < 1) 
     { 
      return new ValidationResult(false, "Value can't be empty"); 
     } 
     else if (noIllegalChars == false) 
     { 
      return new ValidationResult(false, "Ilegal Character"); 
     } 
     else 
     { 
      return new ValidationResult(true, null); 
     } 
    } 
} 
+0

目前尚不清楚問題是什麼。你爲什麼不能把你的保存調用改變的屬性? – Sergey

+0

我得到一個System.Windows.Markup.XamlParseException例外,我想我可以調用序列化的集合,因爲集合稱爲上反序列化。此外,每次屬性收回數據時都會調用該集合,但只有在用戶輸入數據時纔會調用驗證。 – Mulflar

+0

如果您需要區分屬性是否被用戶更改或程序,你可能必須有兩個屬性。一個是核心屬性,另一個只是用於綁定驗證,第二個包裝第一個。 – Sergey

回答

0

好吧,我解決了,但如果有人得到更好的選擇,我會非常感激。

我所做的是我添加了一個裝布爾誰虛假啓動配置文件,我加入到保存功能的條件下工作,只有當加載的是真實的。

的配置類,現在是這樣的:

[Serializable, XmlRoot("configuration")] 
public class Configuration : IDataErrorInfo, INotifyPropertyChanged 
{ 
    private int _minute; 
    [XmlElement] 
    public int minute 
    { 
     get 
     { 
      return _minute; 
     } 
     set 
     { 
      _minute = value; 
      this.Save(); 
      OnPropertyChanged("minute"); 
     } 
    } 
    [XmlIgnore] 
    public bool loaded; 

    public static Configuration Load() 
    { 
    string ConfigPath= AppDomain.CurrentDomain.BaseDirectory + "config.xml"; 
    if (File.Exists(ConfigPath)) 
    { 
     try 
     { 
      XmlSerializer _s = new XmlSerializer(typeof(Configuration)); 
      var tempConf = (Configuracion)_s.Deserialize(new XmlTextReader(ConfigPath)); 
      tempConf.loaded = false; 
      return tempConf; 
     } 
     [...] 
    } 
    public Configuracion() 
    { 
     loaded = false; 
     minutes = 60; 
    } 
    [...] 
} 

我添加了一個Loaded事件到主窗口,並且當它發射它集裝屬性爲true。