Binding a ListBox to an interface's properties in Silverlight
I'm having issues getting my databinding working for a ListBox. I suspect it's because I'm trying to databind against an interface rather than a class.
My C# code:
namespace MyNamespace
{
interface IFoo
{
string Bar { get; }
}
class Fizz
{
private class Buzz : IFoo
{
public string Bar { get { return "something"; } }
}
public IEnumerable<IFoo> GetFoo()
{
List<Buzz> items = new List<Buzz>();
// Populate items
return items;
}
}
}
When I try to do databinding with the output from Fizz::GetFoo()
, it doesn't work. My XAML looks like:
<ListBox Name="listBox1" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock 开发者_开发知识库Text="Bar:" />
<TextBlock Text="{Binding Bar}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When I run it, I see the text for the first TextBlock but not the second. I see errors in the Output window similar to this:
System.Windows.Data Error: Cannot get 'Bar' value (type 'System.String') from 'Buzz' (type 'MyNamespace.Fizz+Buzz'). BindingExpression: Path='Bar' DataItem='Buzz' (HashCode=100433959); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String').. System.MethodAccessException: Attempt to access the method failed: MyNamespace.Fizz+Buzz.get_Bar() at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark) at System.Reflection.RuntimePropertyInfo.InternalGetValue(PropertyInfo thisProperty, Object obj, Object[] index, StacA first chance exception of type 'System.MethodAccessException' occurred in mscorlib.dll
Am I doing something wrong or is what I'm trying to do just not possible?
It looks like everything in your chain needs to be public (and your List
needs to be List<IFoo>
instead of List<Bar>
):
public interface IFoo
{
string Bar { get; }
}
public class Fizz
{
public class Buzz : IFoo
{
public string Bar { get { return "something"; } }
}
public IEnumerable<IFoo> GetFoo()
{
List<IFoo> items = new List<IFoo>();
// Populate items
return items;
}
}
The problem you are running into has to do with reflection across assemblies. The Silverlight code is reflecting on your internal class and interface (classes and interfaces are internal
unless otherwise specified). Even Buzz
needs to be public because it still needs to reflect upon that class, which is private, so it fails.
Obviously, if you were not using data binding here, the code would work fine. You would have access to IFoo
even though Buzz
is private. But, once you bring reflection into the mix, you have to start making things public, unfortunately.
The problem is that your Buzz
class is private, and so the binding engine cannot access the members of that class to perform binding on.
精彩评论