Question

I'm trying to bind controls in a WPF form to an interface and I get a runtime error that it can't find the interface's properties.

Here's the class I'm using as a datasource:

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; }
}

Here's the XAML (an excerpt):

<TextBox Name="userIdTextBox" Text="{Binding UserId}" />
<TextBox Name="userNameTextBox" Text="{Binding UserName}" />
<TextBox Name="emailTextBox" Text="{Binding Email}" />

Here's the code behind (again, an excerpt):

var person = PolicyInjection.Wrap<IPerson>(new Person());
person.UserId = "jdoe";
person.UserName = "John Doe";
person.Email = "jdoe@live.com";

this.DataContext = person;

Note that the class I'm using as the data source needs to be an entity because I'm using Policy Injection through the entlib's Policy Injection Application Block.

I'm getting this error at runtime:

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)'
Was it helpful?

Solution

I'm not familiar with entlib's policy injection, but I'm pretty sure that your problem lies there, and not in the fact that you're using an interface.
If you were to replace

var person = PolicyInjection.Wrap<IPerson>(new Person());

with

IPerson person = new Person();

surely it would work?

OTHER TIPS

We bind to almost nothing but Interfaces in our project, all without problem. The problem you're experiencing is due to entlib... but I'm not familiar enough with entlib to help you there. WPF can, however, bind to Interfaces.

I don't see much wrong with the code. Technically you're binding an instance of the Person class (ie it doesn't make sense to try and bind to an interface anyway) I don't know what your PolicyInjection.Wrap method does, but I'm assuming it returns a concrete Person class? Anyway, I just tried this on my end and it works fine...

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; }
}

I would suggest you look into that PolicyInjection class a bit more. Find out if it really does return a Person type as you expect.

Try to specify property path explicitly in your 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)}" /> 

I guess the type generated by policy injection is based on Person class, but is dynamic and internal. As far as I know XAML data binding engine can work only with public types.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top