Use UIElements as ItemsSource of ListBox in Silverlight

懵懂的女人 提交于 2019-12-13 03:42:51

问题


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 UIElements as ItemsSource in Silverlight the same way as any other objects? Or am I missing something?


回答1:


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!




回答2:


Silverlight and WPF both are differently coded by microsoft, for example yet lot of functionalities of dependency properties are still missing in silverlight 3.0

Now looking at your code, simply means that DisplayMemberPath in silverlight isnt working correctly for dependency objects, but it works better for pure clr objects only for now. However they might come up with an update if you post bug at microsoft connect web site.

Dependency properties are still new in SL 3.0 so we hope to see some improvement in SL 4.0. If you use reflector, you will see that everything like stackpanel and all basic controls differe a lot in implementation in both places.



来源:https://stackoverflow.com/questions/1680213/use-uielements-as-itemssource-of-listbox-in-silverlight

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!