Десериализация класса и привязки WPF - PullRequest
0 голосов
/ 13 сентября 2011

У меня есть небольшая головоломка, которую я пытаюсь решить, и я не уверен, как ее решить ...

Приложение WPF, основанное на подходе MVVM ...

У меня естьКласс SubstitutionionDataSet, который наследуется от DataSet и определяет дополнительную коллекцию:

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
    }
}

... Теперь это суть головоломки..

Приведенные выше классы используются для определения новой таблицы данных в наборе данных, а также для добавления столбцов, строк и времени выполнения.У меня есть другой класс, который позволяет настраивать процесс запутывания, часть конфигурации позволяет выбрать DataTable и DataColumn из SubstituionDataSet, определенного выше.

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
    }
}

У меня есть работающая конфигурация, и я могу настроить несколько запутыванийи затем сериализовать конфигурацию на диск.

Когда я десериализую, я обнаружил, что привязки в графическом интерфейсе не показывают правильные выборы DataTable и DataColumn, DataTable просто показывает полное имя объекта.

В настоящее время я просто пытаюсь заставить работать привязку DataTable - я знаю, что мне нужно переработать привязку DataColumn.

Графический интерфейс пользователя (usercontrol) определяется следующим образом:

<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>

Я надеюсь,Я объяснил проблему достаточно.Кто-нибудь получил какие-либо идеи о том, как я могу заставить его работать, используя текущий дизайн, или изменить подход к достижению того, что мне нужно?

1 Ответ

0 голосов
/ 16 сентября 2011

ОК, кажется, я взломал это сейчас, не то, чтобы кому-то это показалось интересным: -)

Я выложу ответ для потомков ...

Я изменил привязки для Combobox'ов, вот так ...

<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}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...