Silverlight ListBox中的ItemsSource绑定问题

时间:2011-09-13 17:39:05

标签: silverlight c#-4.0 silverlight-4.0

我正在尝试在Silverlight ListBox中列出一些字符串。我将vanilla List绑定到ItemsSource,然后指定要在DisplayMemberPath中显示的List项的属性。我的实现有一些特定的东西会导致ListBox显示模板化项而不是这些项中指定的属性。

这是场景。我有一个派生自UserControl的Parent类,它添加了一个“Title”依赖属性。我创建了一些从Parent派生的Child控件,并指定继承的Title属性。由于某种原因,绑定到ListBox中的Title属性会导致意外行为。这是代码:

public class Parent : UserControl
{
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(Parent), new PropertyMetadata(String.Empty));
}

Child XAML代码(Child1和Child2基本上是相同的XAML,包含简单的代码隐藏)

<v:Parent x:Class="TemplateBindingTest.Child1" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       xmlns:v="clr-namespace:TemplateBindingTest"
       mc:Ignorable="d" Title="Baby 1" Height="41" Width="94">
<Grid x:Name="LayoutRoot" Background="#FFFFBBBB">
    <TextBlock HorizontalAlignment="Center" Text="I da baby" VerticalAlignment="Center" FontSize="14" />
</Grid>

“ViewModel”

public class TheViewModel : INotifyPropertyChanged
{
    public List<Parent> Babies { get; set; }

    public TheViewModel()
    {
        Babies = new List<Parent>();
        Child1 baby1 = new Child1();
        Child2 baby2 = new Child2();
        Babies.Add(baby1);
        Babies.Add(baby2);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

MainPage.xaml中

<UserControl x:Class="TemplateBindingTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:my="clr-namespace:TemplateBindingTest" Height="268" Width="355">

<Grid x:Name="LayoutRoot" Background="White">
    <ListBox ItemsSource="{Binding Path=Babies}" DisplayMemberPath="Title" Height="219" HorizontalAlignment="Left" Margin="12,12,0,0" VerticalAlignment="Top" Width="180"  />
    <my:Child1 HorizontalAlignment="Left" Margin="203,26,0,0" x:Name="child1" VerticalAlignment="Top" />
    <my:Child2 HorizontalAlignment="Left" Margin="203,92,0,0" x:Name="child2" VerticalAlignment="Top" />
</Grid>

因此忽略了在“viewmodel”类中维护UI控件列表有点奇怪的事实,这都是相当简单的Silverlight。在MainPage上的ListBox控件中,我希望看到每个Child控件的标题。相反,Child控件本身会显示在ListBox中。我在这里错过了什么?我觉得很奇怪,Silverlight只是决定在调试输出或其他错误消息中呈现Children控件而不抱怨。就像DisplayMemberPath属性被完全忽略一样。这可能是Silverlight中的错误吗?

error example

为了便于测试,这里是包含上述代码的完整Visual Studio项目的a link

2 个答案:

答案 0 :(得分:1)

这种行为似乎是设计上的。如果列表框看到内容是UIElement的衍生物,那么它就会使您想要显示该内容的简单(并且我认为合理)假设。

你是正确的,你正在做的是“有点奇怪”,你付出了代价。此answer可能会为您提供解决方案。但是,我建议您查看在viewmodel中保存UserControl实例的选项。

答案 1 :(得分:0)

@AnthonyWJones是正确的,他提供的the link导致了这个答案:我需要实现自己的ListBox版本,以实现我的问题中提到的所需功能。

public class MyListBox : ListBox
{
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return false;
    }

    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);
        ((ListBoxItem)element).ContentTemplate = ItemTemplate;
    }
}

我想这个故事的寓意是不要试图直接在ViewModel类中处理UI元素。出于某种原因,这不是最佳实践(绝对不是MVVM)。