2011-09-13 26 views
0

我有一个小的难题,我试图解决,我不知道如何去了解它...类Deserialisation和WPF绑定

基于MVVM方法

WPF应用程序...

我有一个SubstituionDataSet类,从数据集继承和定义了一个附加集合:

namespace Lib 
{ 
    public class SubstitutionDataSet : DataSet 
    { 
     public SubstitutionDataSet() 
     { 
      TableNames = new ObservableCollection<SubstitutionDataTable>(); 

      Tables.CollectionChanging += DataTablesCollectionChanging; 
     } 

     public ObservableCollection<SubstitutionDataTable> TableNames { get; set; } 

     private void DataTablesCollectionChanging(object sender, CollectionChangeEventArgs e) 
     { 
      var actionTable = (DataTable) e.Element; 

      if (e.Action == CollectionChangeAction.Add) 
      { 
       actionTable.Columns.CollectionChanged += DataColumnCollectionChanged; 
       TableNames.Add(new SubstitutionDataTable { Name = actionTable.TableName }); 
      } 
      else if (e.Action == CollectionChangeAction.Remove) 
      { 
       actionTable.Columns.CollectionChanged -= DataColumnCollectionChanged; 
       TableNames.Remove(TableNames.First(tn => tn.Name == actionTable.TableName)); 
      } 
     } 

     private void DataColumnCollectionChanged(object sender, CollectionChangeEventArgs e) 
     { 
      var actionColumn = (DataColumn) e.Element; 
      var hostTable = (DataTable) actionColumn.Table; 
      var hostSubsitutionTable = TableNames.First(tn => tn.Name == hostTable.TableName); 

      if (e.Action == CollectionChangeAction.Add) 
      { 
       hostSubsitutionTable.ColumnNames.Add(actionColumn.ColumnName); 
      } 
      else if (e.Action == CollectionChangeAction.Remove) 
      { 
       hostSubsitutionTable.ColumnNames.Remove(hostSubsitutionTable.ColumnNames.First(cn => cn == actionColumn.ColumnName)); 
      } 
     } 
    } 
} 

随着如下面所定义的SubstitutionDataTable:

namespace Lib 
{ 
    public sealed class SubstitutionDataTable: INotifyPropertyChanged 
    { 
     private string _name; 

     /// <summary> 
     /// The <see cref="Name" /> property's name. 
     /// </summary> 
     private const string NamePropertyName = "Name"; 

     public SubstitutionDataTable() 
     { 
      ColumnNames = new ObservableCollection<string>(); 
     } 

     /// <summary> 
     /// Gets the Name property. 
     /// Changes to that property's value raise the PropertyChanged event. 
     /// </summary> 
     public string Name 
     { 
      get 
      { 
       return _name; 
      } 

      set 
      { 
       if (_name == value) 
       { 
        return; 
       } 

       _name = value; 

       RaisePropertyChanged(NamePropertyName); 
      } 
     } 

     public ObservableCollection<string> ColumnNames { get; set; } 


     #region Implementation of INotifyPropertyChanged 

     /// <summary> 
     /// A property has changed - update bindings 
     /// </summary> 
     [field: NonSerialized] 
     public event PropertyChangedEventHandler PropertyChanged; 

     private void RaisePropertyChanged(string propertyName) 
     { 
      var handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     #endregion 
    } 
} 

...现在这是难题的症结...

上述类用于在DataSet中定义新的DataTable并添加列和行以及运行时。我有另一个允许配置混淆过程的类,配置的一部分允许从上面定义的SubstituionDataSet中选择一个DataTable和DataColumn。

namespace Lib 
{ 
    public class ObfuscationParams : INotifyPropertyChanged 
    { 
     private string _dataColumn; 
     private string _dataTable; 
     private char _maskCharacter; 
     private int _numberCharacters; 

     /// <summary> 
     /// The <see cref="MaskCharacter" /> property's name. 
     /// </summary> 
     private const string MaskCharacterPropertyName = "MaskCharacter"; 
     /// <summary> 
     /// The <see cref="DataColumn" /> property's name. 
     /// </summary> 
     private const string DataColumnPropertyName = "DataColumn"; 
     /// <summary> 
     /// The <see cref="DataTable" /> property's name. 
     /// </summary> 
     private const string DataTablePropertyName = "DataTable"; 


     # region Mask Obfuscation Properties 

     /// <summary> 
     /// Defines whether whitespace is to be trimmed or not for a Mask obfuscation. 
     /// </summary> 
     public bool IsWhiteSpaceTrimmed { get; set; } 

     /// <summary> 
     /// Defines the mask character to be used for a Mask obfuscation. 
     /// </summary> 
     public char MaskCharacter 
     { 
      get { return _maskCharacter; } 
      set 
      { 
       if (_maskCharacter == value) 
        return; 

       _maskCharacter = value; 

       RaisePropertyChanged(MaskCharacterPropertyName); 
      } 
     } 

     /// <summary> 
     /// Defines the number of masking characters to apply. 
     /// </summary> 
     public int NumberCharacters 
     { 
      get { return _numberCharacters; } 
      set { _numberCharacters = value < 1 ? 1 : (value > 16 ? 16 : value); } 
     } 

     /// <summary> 
     /// Defines the mask position for a Mask obfuscation. 
     /// </summary> 
     public MaskPosition MaskPosition { get; set; } 

     #endregion 


     # region Substitute Obfuscation Properties 

     /// <summary> 
     /// Defines which datacolumn is to be used for a Substitution obfuscation. 
     /// </summary> 
     public string DataColumn 
     { 
      get { return _dataColumn; } 
      set 
      { 
       if (_dataColumn == value) 
        return; 

       _dataColumn = value; 

       RaisePropertyChanged(DataColumnPropertyName); 
      } 
     } 

     /// <summary> 
     /// Defines which datatable is to be used for a substitition obfuscation. 
     /// </summary> 
     public string DataTable 
     { 
      get { return _dataTable; } 
      set 
      { 
       if (_dataTable == value) 
        return; 

       _dataTable = value; 

       RaisePropertyChanged(DataTablePropertyName); 
       _dataTable = value; 
      } 
     } 

     #endregion 


     #region Implementation of INotifyPropertyChanged 

     /// <summary> 
     /// A property has changed - update bindings 
     /// </summary> 
     [field: NonSerialized] 
     public virtual event PropertyChangedEventHandler PropertyChanged; 

     private void RaisePropertyChanged(string propertyName) 
     { 
      var handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     #endregion 
    } 
} 

我有配置工作,可以配置一些混淆,然后序列化配置到磁盘。

当我反序列化时,我发现GU​​I上的绑定不显示正确的DataTable和DataColumn选择,DataTable只显示完全限定的对象名称。

我目前只是试图让DataTable绑定工作 - 我知道我需要重做DataColumn绑定。

的GUI(用户控件)被定义为如下:

<UserControl xmlns:igEditors="http://infragistics.com/Editors" x:Class="SubstitutionOptions" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="421" d:DesignWidth="395"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="23" /> 
      <RowDefinition Height="23" /> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="150" /> 
      <ColumnDefinition Width="20" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 

     <TextBlock Grid.Row="0" 
        Grid.Column="0" 
        Text="Dataset" /> 
     <igEditors:XamComboEditor Grid.Row="0" 
            Grid.Column="2" 
            Name="tablesComboBox" 
            NullText="select a dataset..." 
            ItemsSource="{Binding DataContext.Project.SubstitutionDataSet.TableNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 
            DisplayMemberPath="Name" 
            SelectedItem="{Binding DataContext.SelectedFieldSubstitutionDataTable, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> 

     <TextBlock Grid.Row="1" 
        Grid.Column="0" 
        Text="Column" /> 
     <igEditors:XamComboEditor Grid.Row="1" 
            Grid.Column="2" 
            NullText="select a column..." 
            ItemsSource="{Binding DataContext.SelectedFieldSubstitutionDataTable.ColumnNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 
            SelectedItem="{Binding DataColumn, Mode=TwoWay}"/> 
    </Grid> 
</UserControl> 

希望已充分解释的问题。有没有人有过关于如何使用当前设计工作或重新设计方法来实现我所需的任何想法?

+0

OK,没回复...... 我其实已经部分解决该问题的工作。我已经重写了SubstitutionDataTable上的equals运算符。当对象被反序列化时,我得到组合框的工作,几乎... 我发现我看的第一个字段已正确绑定,但每次点击另一个字段时,它都包含第一个绑定中提供的... 嗯,有什么想法? – Drammy

回答

0

OK,想我已经破解了,现在,不是每个人似乎兴趣:-)

我会后留给后人虽然答案...

我改变了绑定的组合框状所以......

<TextBlock Grid.Row="0" 
      Grid.Column="0" 
      Text="Dataset" /> 
<igEditors:XamComboEditor Grid.Row="0" 
          Grid.Column="2" 
          NullText="select a dataset..." 
          ItemsSource="{Binding DataContext.VDOProject.SubstitutionDataSet.TableNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 
          DisplayMemberPath="Name" 
          Text="{Binding DataTable, Mode=TwoWay}" 
          SelectedItem="{Binding DataContext.SelectedFieldSubstitutionDataTable, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> 

<TextBlock Grid.Row="1" 
      Grid.Column="0" 
      Text="Column" /> 
<igEditors:XamComboEditor Grid.Row="1" 
          Grid.Column="2" 
          NullText="select a column..." 
          ItemsSource="{Binding DataContext.SelectedFieldSubstitutionDataTable.ColumnNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 
          Text="{Binding DataColumn, Mode=TwoWay}" />