在 Silverlight 中使用 UIElements 作为 ListBox 的 ItemsSource

发布于 2024-08-10 18:30:56 字数 1092 浏览 7 评论 0 原文

我注意到,如果您有任何从 UIElement 派生为 Silverlight 中 ListBox 中的项目的内容,它会按原样呈现对象,并且不会关注 ListBox 的设置。代码> DisplayMemberPath 和/或<代码>ListBox.ItemTemplate

例如,如果您有这样的 XAML:

<ListBox Width="200" Height="300" DisplayMemberPath="Tag">
    <TextBlock Tag="tag1">text1</TextBlock>
    <TextBlock Tag="tag2">text2</TextBlock>
    <TextBlock Tag="tag3">text3</TextBlock>
</ListBox>

在 Siverlight 中,这会生成一个包含如下项目的 ListBox

text1
text2
text3

但是在 WPF 中(我认为这是正确的行为),它会按预期列出标签:

tag1
tag2
tag3

如果我使用以下对象不是从 UIElement 继承的,一切都按预期工作:

<ListBox Width="200" Height="300" DisplayMemberPath="[0]">
    <sys:String>abcde</sys:String>
    <sys:String>fgh</sys:String>
</ListBox>

Produces:

a
f

有没有办法像任何其他对象一样在 Silverlight 中使用 UIElement 作为 ItemsSource ?或者我错过了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

み青杉依旧 2024-08-17 18:30:56

问题似乎出在 ItemsControlBase 类中的 PrepareContainerForItemOverride 方法中。如果您在反射器中查看该方法,您会发现,如果该项目是 UIElement,则不会调用使用 DisplayMemberPath 填充项目的逻辑。

如果您想获得所需的行为,则需要对 ListBox 控件进行子类化并重写此方法,并设置您想要在 ListBoxItems 上设置的值。

下面是一个示例:

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

    }
}

您需要有一个 ItemTemplate 才能正常工作。 DisplayMemberPath 属性的实现稍微复杂一些。

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

不要忘记添加本地的 xmlns 并将其设置为实现该控件的程序集。

祝你好运!

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!

ぃ弥猫深巷。 2024-08-17 18:30:56

Silverlight 和 WPF 的编码方式都不同,例如,silverlight 3.0 中仍然缺少依赖属性的许多功能

现在查看您的代码,仅意味着 silverlight 中的 DisplayMemberPath 无法正确用于依赖对象,但目前它仅适用于纯 clr 对象。但是,如果您在 microsoft connect 网站上发布错误,他们可能会提供更新。

依赖属性在 SL 3.0 中仍然是新的,因此我们希望在 SL 4.0 中看到一些改进。如果你使用反射器,你会发现像 stackpanel 这样的东西和所有基本控件在这两个地方的实现都有很大的不同。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文