O WPF não consegue vincular dados a uma interface?
-
09-06-2019 - |
Pergunta
Estou tentando vincular controles em um formulário WPF a uma interface e recebo um erro de tempo de execução informando que não é possível encontrar as propriedades da interface.
Aqui está a classe que estou usando como fonte de dados:
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; }
}
Aqui está o XAML (um trecho):
<TextBox Name="userIdTextBox" Text="{Binding UserId}" />
<TextBox Name="userNameTextBox" Text="{Binding UserName}" />
<TextBox Name="emailTextBox" Text="{Binding Email}" />
Aqui está o código por trás (novamente, um trecho):
var person = PolicyInjection.Wrap<IPerson>(new Person());
person.UserId = "jdoe";
person.UserName = "John Doe";
person.Email = "jdoe@live.com";
this.DataContext = person;
Observe que a classe que estou usando como fonte de dados precisa ser uma entidade porque estou usando a Injeção de Política por meio do Bloco de Aplicativo de Injeção de Política do entlib.
Estou recebendo este erro em tempo de execução:
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)'
Solução
Não estou familiarizado com a injeção de política do entlib, mas tenho certeza de que o seu problema está aí, e não no fato de você estar usando uma interface.
Se você fosse substituir
var person = PolicyInjection.Wrap<IPerson>(new Person());
com
IPerson person = new Person();
certamente funcionaria?
Outras dicas
Não nos ligamos a quase nada além de Interfaces em nosso projeto, tudo sem problemas.O problema que você está enfrentando é devido ao entlib...mas não estou familiarizado o suficiente com o entlib para ajudá-lo nisso.O WPF pode, no entanto, vincular-se a interfaces.
Não vejo muita coisa errada com o código.Tecnicamente, você está vinculando uma instância da classe Person (ou seja, não faz sentido tentar vincular a uma interface de qualquer maneira). Não sei o que o seu método PolicyInjection.Wrap faz, mas presumo que ele retorne um valor concreto Classe de pessoa?De qualquer forma, tentei isso do meu lado e funciona bem ...
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; }
}
Eu sugiro que você analise um pouco mais essa classe PolicyInjection.Descubra se ele realmente retorna um tipo Person conforme o esperado.
Tente especificar o caminho da propriedade explicitamente no seu 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)}" />
Acho que o tipo gerado pela injeção de política é baseado na classe Person, mas é dinâmico e interno.Até onde eu sei, o mecanismo de vinculação de dados XAML só pode funcionar com tipos públicos.