Я пытаюсь привязать элементы управления в форме 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 = "[email protected]";
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();
конечно, это сработает?
Роберт прав - проблема в том, что привязка данных WPF не распознает свойства прокси-класса, которые создает PolicyInjection.Wrap. Связывание данных отлично работает без PI, поэтому мне просто нужно придумать обходной путь, который не использует его.
Я не вижу ничего плохого в коде. Технически вы привязываете экземпляр класса 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, как вы ожидали.
В нашем проекте мы привязываемся практически ни к чему, кроме интерфейсов, и все это без проблем. Проблема, с которой вы столкнулись, связана с entlib ... но я недостаточно знаком с entlib, чтобы помочь вам в этом. Однако WPF может связываться с интерфейсами.
Попробуйте явно указать путь к свойству в 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 может работать только с общедоступными типами.
@Robert Jeppesen: это не позволяет запускать его код PolicyInjection.