WPF привязка данных к интерфейсу, а не к фактическому объекту – возможность литья?

Скажем, у меня есть такой интерфейс:

public interface ISomeInterface { ... } 

У меня также есть пара classов, реализующих этот интерфейс;

 public class SomeClass : ISomeInterface { ... } 

Теперь у меня есть элементы списка ListBox WPF для ISomeInterface, используя пользовательский DataTemplate.

Механизм привязки данных, по-видимому, не (который я смог выяснить) позволяет мне привязываться к свойствам интерфейса – он видит, что объект является объектом SomeClass, а данные отображаются только в том случае, если SomeClass должен иметь свойство bound, доступное как свойство без интерфейса.

Как я могу заставить DataTemplate действовать так, как если бы каждый объект был ISomeInterface, а не SomeClass и т. Д.?

Благодаря!

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

неявный:

 {Binding Path=MyValue} 

явный:

 {Binding Path=(mynamespacealias:IMyInterface.MyValue)} 

Этот ответ от форумов Microsoft Беатрис Коста – MSFT стоит прочитать (довольно старый):

Команда привязки данных обсудила добавление поддержки интерфейсов некоторое время назад, но в итоге не реализовала ее, потому что мы не смогли создать хороший дизайн для нее. Проблема заключалась в том, что интерфейсы не имеют такой иерархии, как типы объектов. Рассмотрим сценарий, в котором ваш источник данных реализует как IMyInterface1 и IMyInterface2 и у вас есть DataTemplates для обоих этих интерфейсов в ресурсах: какой DataTemplate вы думаете, что мы должны подобрать?

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

Другая вещь, которую мы должны были иметь в виду, состоит в том, что reflection не так уж и дешево, и это уменьшит наш принцип для этого сценария.

Так в чем же решение? Вы не можете сделать все это в XAML, но вы можете сделать это легко с небольшим количеством кода. Свойство ItemTemplateSelector элемента ItemsControl можно использовать для выбора того DataTemplate который вы хотите использовать для каждого элемента. В методе SelectTemplate для вашего селектора шаблонов вы получаете в качестве параметра элемент, который вы создадите. Здесь вы можете проверить, какой интерфейс он реализует, и вернуть DataTemplate который соответствует ему.

Короткий ответ – DataTemplate не поддерживает интерфейсы (подумайте о множественном наследовании, явном v) неявном и т. Д.). Способ, которым мы стремимся обойти это, состоит в том, чтобы расширить возможности базового classа, чтобы дать возможность специализации / обобщения DataTemplate. Это означает, что это достойное, но не обязательно оптимальное решение:

 public abstract class SomeClassBase { } public class SomeClass : SomeClassBase { }    

Ответ, предложенный dummyboy, является лучшим ответом (его следует проголосовать за верхний imo). У этого есть проблема, которую конструктор ему не нравится (дает ошибку «Object null не может использоваться как параметр accessor для PropertyPath), но есть хорошее обходное решение. Обходной путь состоит в том, чтобы определить элемент в datatemplate, а затем установите шаблон в метку или другой элемент управления содержимым. В качестве примера я пытался добавить изображение, подобное этому

  

Но он продолжал давать мне ту же ошибку. Решением было создание ярлыка и использование шаблона данных для показа моего контента

  

У этого есть свои недостатки, но это, кажется, работает очень хорошо для меня.

У вас есть другой вариант. Установите ключ на свой DataTemplate и укажите этот ключ в ItemTemplate. Как это:

    

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

   

Rendering

Примечание. Вы можете использовать более сложные многочастные пути, подобные этому, если свойство интерфейса находится внутри пути:

       

Или напрямую с директивой Binding .

   

Или при использовании нескольких свойств интерфейса вы можете переопределить DataContext локально, чтобы сделать код более удобочитаемым.

      

Совет. Следите за тем, чтобы случайно закончилось )} в конце выражения Path. Глупая ошибка копирования / вставки. Я продолжаю делать.

Path="(myNameSpace:IShippingPackage.ShippingMethod)}"


Обязательно используйте Path=

Обнаружено, что если я явно не использую Path= тогда он не сможет проанализировать привязку. Обычно я просто пишу что-то вроде этого:

 Text="{Binding FirstName}" 

вместо

 Text="{Binding Path=FirstName}" 

Но с более сложной привязкой интерфейса я обнаружил, что Path= необходимо для исключения этого исключения:

 System.ArgumentNullException: Key cannot be null. Parameter name: key at System.Collections.Specialized.ListDictionary.get_Item(Object key) at System.Collections.Specialized.HybridDictionary.get_Item(Object key) at System.ComponentModel.PropertyChangedEventManager.RemoveListener(INotifyPropertyChanged source, String propertyName, IWeakEventListener listener, EventHandler`1 handler) at System.ComponentModel.PropertyChangedEventManager.RemoveHandler(INotifyPropertyChanged source, EventHandler`1 handler, String propertyName) at MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32 k, Object newO, Object parent) at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange) 

т.е. не делайте этого:

  
  • Привязка OneWayToSource от свойства readonly в XAML
  • Как правильно привязать xml к WPF DataGrid?
  • Заполнить Combobox из базы данных
  • WPF перед записью
  • Для чего нужен DataContext?
  • Почему привязка данных WPF к исключению ласточки?
  • WPF привязка к локальной переменной
  • Когда следует использовать # и = в элементах управления ASP.NET?
  • Связывающие свойства в коде
  • Как я могу привязать данные строк к ListBox в WPF / WP7?
  • Принуждение WPF TextBox больше не работает в .NET 4.0
  • Давайте будем гением компьютера.