2011-09-13 2 views
1

Я пытаюсь перечислить некоторые строки в Silverlight ListBox. Я привязываю ваниль List к ItemsSource, а затем указываю свойство списка, которое должно отображаться в DisplayMemberPath. Для моей реализации есть что-то конкретное, что заставляет ListBox отображать шаблонные элементы вместо свойства, указанного внутри этих элементов.Проблема с ItemsSource привязка в Silverlight ListBox

Вот сценарий. У меня есть родительский класс, который происходит от UserControl, который добавляет свойство зависимостей Title. Я создаю несколько элементов управления Child, которые берутся из родителя и укажу, что унаследовало свойство Title. По какой-то причине привязка к этому свойству Title в ListBox вызывает непредвиденное поведение. Вот код:

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

Код Детский XAML (Child1 и Child2 в основном такие же XAML с тривиальными codebehinds)

<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», это все довольно просто Silverlight. В элементе управления ListBox на MainPage я ожидаю увидеть заголовок для каждого элемента управления Child. Вместо этого дочерние элементы управления сами отображаются в ListBox. Что мне здесь не хватает? Мне очень странно, что Silverlight просто решает отобразить элементы управления «Дети» без каких-либо претензий в Debug Output или других сообщениях об ошибках. Это похоже на то, что атрибут DisplayMemberPath полностью игнорируется. Может ли это быть ошибкой в ​​Silverlight?

error example

Для удобства тестирования, вот a link до полного Visual Studio проекта, содержащий код, приведенный выше.

ответ

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. Это не лучшая практика (и определенно не MVVM) по какой-то причине.

1

Такое поведение, кажется, по дизайну. Если в списке видно, что Контент является производным от UIElement, тогда он делает простое (и я думаю разумным) предположение, что вы намерены отображать этот контент.

Вы правы, что вы делаете, это «немного странно», и вы платите цену. Это answer может содержать решение для вас. Однако я бы рекомендовал вам пересмотреть выбор, чтобы держать экземпляр UserControl в модели view.

Смежные вопросы