【问题标题】:Use UIElements as ItemsSource of ListBox in Silverlight在 Silverlight 中使用 UIElements 作为 ListBox 的 ItemsSource
【发布时间】:2009-11-05 12:22:06
【问题描述】:

我注意到,如果您有任何从 UIElement 派生的项目作为 Silverlight 中的 ListBox 中的项目,它会按原样呈现对象并且不注意 DisplayMemberPath 和/或 @987654324 的设置@。

例如,如果您有这样的 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>

生产:

a
f

有什么方法可以像使用其他对象一样在 Silverlight 中使用 UIElements 作为 ItemsSource?还是我错过了什么?

【问题讨论】:

  • 我没有答案,有点像 Silverlight 中的错误。不过老实说,我的问题应该是:为什么首先要使用框架元素作为数据源?
  • 好吧,我相信你可以想出很多方案。我真正的评论有点太长了。但是,例如,您可能在其他一些容器中有一个控件列表。假设您的列表框中显示了某个 StackPanel 中的控件列表,并且您希望显示这些控件的 Name 属性。

标签: wpf silverlight data-binding itemssource uielement


【解决方案1】:

看起来问题出在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 并将其设置为实现该控件的程序集。

祝你好运!

【讨论】:

  • 谢谢,正是我的想法。一个很酷的例子(如果这不是太麻烦的话)。
  • 一个小补充:你必须调用 base.PrepareContainerForItemOverride(element, item);让您的自定义 ListBox 可以运行。不幸的是,这种方法在 ComboBox 上失败了。它适用于下拉项目,但不适用于选定项目,我似乎找不到修改 SelectionBoxItemTemplate 的方法,因为它的设置访问器是内部的。
【解决方案2】:

Silverlight 和 WPF 都由微软进行了不同的编码,例如,silverlight 3.0 中仍然缺少许多依赖属性的功能

现在查看您的代码,仅表示silverlight 中的DisplayMemberPath 对于依赖对象不能正常工作,但目前仅对纯 clr 对象工作得更好。但是,如果您在 microsoft connect 网站上发布错误,他们可能会提出更新。

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

【讨论】:

    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 2010-11-03
    相关资源
    最近更新 更多