我正在尝试在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中的错误吗?
为了便于测试,这里是包含上述代码的完整Visual Studio项目的a link。
答案 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)。