Свойства привязки данных POCO - PullRequest
17 голосов
/ 02 марта 2009

Существуют ли какие-либо структуры привязки данных (BCL или иным образом), которые позволяют связывать между любые два свойства CLR , которые реализуют INotifyPropertyChanged и INotifyCollectionChanged? Кажется, должно быть возможно сделать что-то вроде этого:

var binding = new Binding();
binding.Source = someSourceObject;
binding.SourcePath = "Customer.Name";
binding.Target = someTargetObject;
binding.TargetPath = "Client.Name";
BindingManager.Bind(binding);

Где someSourceObject и someTargetObject - это просто POCO, которые реализуют INotifyPropertyChanged. Однако мне неизвестно о какой-либо поддержке BCL для этого, и я не уверен, что существуют существующие платформы, которые позволяют это.

ОБНОВЛЕНИЕ : Поскольку доступной библиотеки не существует, я взял на себя ответственность написать свою собственную. Это доступно здесь .

Спасибо

Ответы [ 6 ]

10 голосов
/ 11 июня 2009

Я написал Ферма , чтобы заполнить пустоту.

7 голосов
/ 10 марта 2009

Мне не известна какая-либо библиотека , которая делает это, но вы можете написать свою собственную довольно легко.

Вот база, которую я обнаружил за несколько минут, которая устанавливает двухстороннюю привязку данных между двумя простыми свойствами:

public static class Binder
{

    public static void Bind(
        INotifyPropertyChanged source,
        string sourcePropertyName,
        INotifyPropertyChanged target,
        string targetPropertyName)
    {
        var sourceProperty
            = source.GetType().GetProperty(sourcePropertyName);
        var targetProperty
            = target.GetType().GetProperty(targetPropertyName);

        source.PropertyChanged +=
            (s, a) =>
            {
                var sourceValue = sourceProperty.GetValue(source, null);
                var targetValue = targetProperty.GetValue(target, null);
                if (!Object.Equals(sourceValue, targetValue))
                {
                    targetProperty.SetValue(target, sourceValue, null);
                }
            };

        target.PropertyChanged +=
            (s, a) =>
            {
                var sourceValue = sourceProperty.GetValue(source, null);
                var targetValue = targetProperty.GetValue(target, null);
                if (!Object.Equals(sourceValue, targetValue))
                {
                    sourceProperty.SetValue(source, targetValue, null);
                }
            };
    }
}

Конечно, в этом коде не хватает нескольких тонкостей. Вещи, чтобы добавить включают

  • Проверка того, что source и target назначены
  • Проверка наличия свойств, обозначенных sourcePropertyName и targetPropertyName
  • Проверка совместимости типов между двумя свойствами

Кроме того, Reflection относительно медленный (хотя тестируйте его перед тем, как выбросить, он не , а медленный), поэтому вы можете использовать вместо этого скомпилированные выражения.

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

Binder.Bind( source, "Name", target, "Name")

вы могли бы написать

source.Bind( Name => target.Name);
1 голос
/ 06 марта 2009

Может быть Bindable LINQ или непрерывный linq может помочь здесь. Если вы пытаетесь добавить свойства модели, которые на самом деле являются «производными свойствами» ваших актуальных, обновляемых данных, чтобы облегчить привязку пользовательского интерфейса, эти две платформы должны помочь.

1 голос
/ 06 марта 2009

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

0 голосов
/ 16 ноября 2016

Я написал небольшой проект Bind с полной поддержкой привязки между необходимыми свойствами асинхронных действий привязки. Синтаксис не может быть проще:

//Two way binding between neasted properties:
Bind.TwoWay(()=> client.Area.Data.Name == this.AreaName);

//On change action execute:
Bind
    .OnChange(()=> client.Personal.Name)
    .Do(x => clientName = x);
0 голосов
/ 11 марта 2009

Если вы определили свои свойства как DependencyProperty , вы можете сделать это. И WF, и WPF имеют его реализацию (первая ссылка для WPF. Для WF это this one), поэтому вам нужно решить, какой из них использовать - но обоих должно хватить для ваших нужд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...