WPF не может привязать данные к интерфейсу?
-
09-06-2019 - |
Вопрос
Я пытаюсь привязать элементы управления в форме WPF к интерфейсу и получаю ошибку времени выполнения, из-за которой не удается найти свойства интерфейса.
Вот класс, который я использую в качестве источника данных:
public interface IPerson
{
string UserId { get; set; }
string UserName { get; set; }
string Email { get; set; }
}
public class Person : EntityBase, IPerson
{
public virtual string UserId { get; set; }
public string UserName { get; set; }
public virtual string Email { get; set; }
}
Вот XAML (отрывок):
<TextBox Name="userIdTextBox" Text="{Binding UserId}" />
<TextBox Name="userNameTextBox" Text="{Binding UserName}" />
<TextBox Name="emailTextBox" Text="{Binding Email}" />
Вот код (опять же, отрывок):
var person = PolicyInjection.Wrap<IPerson>(new Person());
person.UserId = "jdoe";
person.UserName = "John Doe";
person.Email = "jdoe@live.com";
this.DataContext = person;
Обратите внимание, что класс, который я использую в качестве источника данных, должен быть сущностью, поскольку я использую внедрение политики через блок приложения внедрения политики entlib.
Я получаю эту ошибку во время выполнения:
System.Windows.Data Error: 16 : Cannot get 'Email' value (type 'String') from '' (type 'Person'). BindingExpression:Path=Email; DataItem='Person' (HashCode=22322349); target element is 'TextBox' (Name='emailTextBox'); target property is 'Text' (type 'String') TargetException:'System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'
Решение
Я не знаком с внедрением политики entlib, но я почти уверен, что ваша проблема заключается именно в этом, а не в том, что вы используете интерфейс.
Если бы вы заменили
var person = PolicyInjection.Wrap<IPerson>(new Person());
с
IPerson person = new Person();
наверняка это сработает?
Другие советы
В нашем проекте мы практически ни к чему не привязываемся, кроме интерфейсов, и все без проблем.Проблема, с которой вы столкнулись, связана с entlib...но я недостаточно знаком с entlib, чтобы помочь вам в этом.Однако WPF может привязываться к интерфейсам.
Я не вижу ничего плохого в коде.Технически вы привязываете экземпляр класса Person (т.е. в любом случае нет смысла пытаться привязываться к интерфейсу). Я не знаю, что делает ваш метод PolicyInjection.Wrap, но я предполагаю, что он возвращает конкретный Класс человека?В любом случае, я только что попробовал это на своей стороне, и все работает нормально...
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
IPerson person = new Person() { FirstName = "Hovito" };
this.DataContext = person;
}
}
public class Person : IPerson
{
public virtual string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
Я бы посоветовал вам более подробно изучить этот класс PolicyInjection.Выясните, действительно ли он возвращает тип Person, как вы ожидаете.
Попробуйте явно указать путь к свойству в XAML:
<TextBox Name="userIdTextBox" Text="{Binding (myns:IPerson.UserId)}" />
<TextBox Name="userNameTextBox" Text="{Binding (myns:IPerson.UserName)}" />
<TextBox Name="emailTextBox" Text="{Binding (myns:IPerson.Email)}" />
Я предполагаю, что тип, созданный путем внедрения политики, основан на классе Person, но является динамическим и внутренним.Насколько мне известно, механизм привязки данных XAML может работать только с общедоступными типами.