I've noticed that if you have anything deriving from UIElement
as items in a ListBox
in Silverlight it renders the object as is and isn't paying any attention to settings of DisplayMemberPath
and/or ListBox.ItemTemplate
.
For example if you have XAML like this:
<ListBox Width="200" Height="300" DisplayMemberPath="Tag">
<TextBlock Tag="tag1">text1</TextBlock>
<TextBlock Tag="tag2">text2</TextBlock>
<TextBlock Tag="tag3">text3</TextBlock>
</ListBox>
In Siverlight this produces a ListBox
with items like this:
text1
text2
text3
However in WPF (and I think this is correct behavior) it lists tags as expected:
tag1
tag2
tag3
If I use objects that aren't inherited from UIElement everything works as expected:
<ListBox Width="200" Height="300" DisplayMemberPath="[0]">
<sys:String>abcde</sys:String>
<sys:String>fgh</sys:String>
</ListBox>
Produces:
a
f
Is there any way to use UIElement
s as ItemsSource
in Silverlight the same way as any other objects? Or am I missing something?
It looks like the issue is in the PrepareContainerForItemOverride
method in ItemsControlBase
class. If you look at that method in reflector you will see that if the item is a UIElement
then the logic to populate the items using the DisplayMemberPath
doesn't get called.
If you want to get the behavior you are after you would need to subclass the ListBox
control and override this method and set the values you want set on the ListBoxItems
.
Here is an example:
public class MyListBox : ListBox
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
if (!object.ReferenceEquals(element, item))
{
ContentControl control = element as ContentControl;
if (control == null || this.ItemTemplate == null)
{
return;
}
control.Content = item;
control.ContentTemplate = this.ItemTemplate;
}
}
}
And you need to have an ItemTemplate
for this to work. The DisplayMemberPath
property is a little more complicated to implement.
<local:MyListBox Width="200" Height="300" DisplayMemberPath="Tag">
<local:MyListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Tag}" />
</DataTemplate>
</local:MyListBox.ItemTemplate>
<TextBlock Tag="tag1">text1</TextBlock>
<TextBlock Tag="tag2">text2</TextBlock>
<TextBlock Tag="tag3">text3</TextBlock>
</local:MyListBox>
Don't forget to add the xmlns for the local and set it to your assembly that implements the control.
Good luck!