Проблема с привязкой ItemsSource в Silverlight ListBox - PullRequest
1 голос
/ 13 сентября 2011

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

Вот сценарий.У меня есть родительский класс, производный от UserControl, который добавляет свойство зависимости «Заголовок».Я создаю несколько дочерних элементов управления, производных от Parent, и указываю, что унаследовано свойство 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 с тривиальными кодами)

<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 на главной странице я ожидаю увидеть заголовок для каждого дочернего элемента управления.Вместо этого дочерние элементы управления отображаются в ListBox.Что мне здесь не хватает?Я нахожу очень странным, что Silverlight просто решает визуализировать элементы управления Children без жалоб в выводе отладки или других сообщениях об ошибках.Как будто атрибут DisplayMemberPath полностью игнорируется.Может ли это быть ошибкой в ​​Silverlight?

error example

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

Ответы [ 2 ]

1 голос
/ 14 сентября 2011

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

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

0 голосов
/ 14 сентября 2011

@ AnthonyWJones верен, и предоставленная им ссылка привела к этому ответу: мне нужно было бы реализовать мою собственную взломанную версию 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) по причине.

...