Как сохранить свойства в синхронизации - PullRequest
0 голосов
/ 06 января 2020

Учитывая следующие классы ниже, я ищу лучший способ сохранить Параметры из ExecuteQuery класса в синхронизации c с Параметры из Query класса.

Я работаю в проекте WPF с использованием двух представлений и моделей представления, одно представление - определение модели Query, привязка DataGrid к Parameters. Другое представление - определить модель ExecuteQuery, в которой есть ComboBox для выбора целевого объекта Query. Как только он выбран, я хочу скопировать параметры из запроса в ExecuteQuery, чтобы он синхронизировался, и любое изменение коллекции и свойств можно было отслеживать и отражать в ExecuteQuery соответствующим образом.

public class NameParameter : Entity
{
    private string _name;
    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }
}

public class KeyValueParameter : ClientEntity
{
    private string _name;
    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }

    private string _value;
    public string Value
    {
        get => _value;
        set => SetProperty(ref _value, value);
    }
}

public class Query
{
    private ObservableCollection<NameParameter> _parameters = new ObservableCollection<NameParameter>();
    public IEnumerable<NameParameter> Parameters => _parameters.AsEnumerable();

    public void AddParameter()
    {
        _parameters.Add(new NameParameter());
    }
}

public class ExecuteQuery
{
    private Query _query;
    public Query Query
    {
        get => _query;
        set => SetProperty(ref _query, value);
    }

    private ObservableCollection<KeyValueParameter> _parameters = new ObservableCollection<KeyValueParameter>();
    public IEnumerable<KeyValueParameter> Parameters => _parameters.AsEnumerable();
}

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

var configuration = new MapperConfiguration(cfg => {
    cfg.AllowNullCollections = true;
    cfg.CreateMap<NameParameter, KeyValueParameter>()
        .ForMember(d => d.Value, o => o.Ignore());
});

Я могу добиться этого с некоторыми усилиями, но задавая этот вопрос здесь, чтобы узнать экспертное решение для решения такой повторяющейся проблемы с минимальными изменениями кода и определить любой шаблон, который использует большинство людей.

1 Ответ

0 голосов
/ 07 января 2020

Спасибо, Хольгер, за ваши комментарии. Наконец, вот как я достиг этого с таким большим количеством событий, которые кажутся грязными. Не уверен, что есть лучший и чистый способ сделать это.

Первоначально я намеревался опубликовать этот вопрос, пытаясь найти какой-либо умелый способ абстрагирования этого логика c от объектов моего домена.

public class Query
{
    private ObservableCollection<NameParameter> _parameters = new ObservableCollection<NameParameter>();
    public IEnumerable<NameParameter> Parameters => _parameters.AsEnumerable();

    public void AddParameter()
    {
        _parameters.Add(new NameParameter());
    }

    public void SubscribeParametersCollectionChanges(NotifyCollectionChangedEventHandler handler)
    {
        _parameters.CollectionChanged += handler;
    }
}

public class ExecuteQuery
{
    public ExecuteQuery()
    {
        PropertyChanged += ExecuteQuery_PropertyChanged;
    }

    private void ExecuteQuery_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Query))
            OnQuerySelection();
    }

    private Query _query;
    public Query Query
    {
        get => _query;
        set => SetProperty(ref _query, value);
    }

    private ObservableCollection<KeyValueParameter> _parameters = new ObservableCollection<KeyValueParameter>();
    public IEnumerable<KeyValueParameter> Parameters => _parameters.AsEnumerable();

    private void OnQuerySelection()
    {
        // subscribe to NamedParameters collection changed events
        DataElement?.SubscribeParametersCollectionChanges(Parameters_CollectionChanged);
        // calling this method explicitly so that if there are already Parameters in Source, bring them right away
        Parameters_CollectionChanged(this, null);
    }

    private void Parameters_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // subscribe to each object property changed events in NamedParameters 
        foreach (var namedParameter in Query.Parameters)
            if (namedParameter is INotifyPropertyChanged npc)
                npc.PropertyChanged += Parameters_PropertyChanged;
        // copying parameters from source to target
        _parameters = new ObservableCollection<KeyValueParameter>(
            Query.Parameters.Select(x => new KeyValueParameter(x.Name)));
        // raising event to notify UI for this change
        RaisePropertyChanged(nameof(Parameters));
    }

    private void Parameters_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Name))
        {
            var namedParameter = Query.Parameters.ToList();
            for (var i = 0; i < namedParameter.Count; i++)
                _parameters[i].Name = namedParameter[i].Name;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...