ListBox SelectedItem не обновляет DataTemplate

Следующая проблема: у меня есть DataModel, содержащая список объектов и ссылку на выбранный объект внутри списка (среди прочего) Все работает нормально - если я выбираю s.th. в ListBox это также доступно в SelectedItem - если я изменяю s.th. в SelectedItem он обновляется во всей DataModel.

..С одним исключением: Контент ListBox не обновляется. Я подозреваю, что это как-то связано с DataTemplate, потому что я могу наблюдать следующее:

  • если я изменяю SelectedItem, список элементов в DataModel соответствующим образом обновляется (проверено на отладчике - также я всегда вижу правильные данные в окне редактирования выбранного элемента)
  • ListBox обновляется, если я добавляю объект из списка внутри DataModel, НО также во время этого обновления я получаю только новый элемент в ListBox, существующие тексты не обновляются (поэтому список фактически отражает данные из DataModel)
  • Если я перезагружаю DataModel, вся ListBox перестраивается, и отображаемые данные верны (поэтому в источнике Binding нет ничего плохого)

Обновление: новая информация о точной проблеме

Проблема на самом деле в некоторой комбинации расширений Xsd2Code и ComplexType (в XSD). Я не думаю, что это ошибка в Xsd2Code, сгенерированный код выглядит хорошо.

Используемый файл XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="SampleRoot">
        <xs:complexType>
            <xs:sequence minOccurs="0" maxOccurs="30">
                <xs:element name="SampleElement">
                    <xs:complexType>
                        <xs:complexContent>
                            <xs:extension base="SampleElement"/>
                        </xs:complexContent>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="SampleElement">
        <xs:attribute name="Name" type="xs:string" use="required"/>
    </xs:complexType>
</xs:schema>

Используемая DataModel (упрощенная, PropertyChanged правильно реализована, классы SampleRootSampleElement а также SampleRoot генерируются Xsd2Code):

public class DataModel : INotifyPropertyChanged
{
    public SampleRootSampleElement SelectedItem;
    public SampleRoot Root;
}

Что касается XAML, здесь нет ничего особенного:

    <ListBox Height="211" HorizontalAlignment="Left" Margin="12,12,0,0" Name="listBoxNames" VerticalAlignment="Top" Width="189" ItemsSource="{Binding Root.SampleElement}" SelectedItem="{Binding SelectedItem}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <TextBox HorizontalAlignment="Left" Margin="12,229,0,0" Name="textBoxName" VerticalAlignment="Top" Width="189" Text="{Binding SelectedItem.Name}" />

Эта комбинация показывает описанное поведение. Чтобы исправить это поведение, я могу удалить расширение для SampleElement внутри XSD, который уменьшает XSD до:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="SampleRoot">
        <xs:complexType>
            <xs:sequence minOccurs="0" maxOccurs="30">
                <xs:element name="SampleElement" type="SampleElement"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="SampleElement">
        <xs:attribute name="Name" type="xs:string" use="required"/>
    </xs:complexType>
</xs:schema>

Все остальное остается прежним, за исключением того, что нет SampleRootSampleElement сгенерированный класс (который был расширением ранее). Вместо SampleElement непосредственно используется:

public class DataModel : INotifyPropertyChanged
{
    public SampleElement SelectedItem;
    public SampleRoot Root;
}

Эти несколько изменений заставляют все работать как положено - с недостатком, что расширения не могут использоваться. Так что же плохого в первом подходе, если я хочу расширять сложные типы?

1 ответ

TextBlock значение не было обновлено из-за двух возможных, но связанных проблем:

  • Ваш Asset (не знаю, что является базовым типом) класс не реализует INotifyPropertyChanged интерфейс.
  • Если вы реализовали PropertyChanged обработчик событий - используйте его в Name сеттер:

public string Name 
{ 
    get
    {
        return this.name;
    }

    set
    {
        this.name = value;
        this.OnPropertyChanged("Name");
    }
}

После применения обоих предложений ваш пример будет работать как положено.

Другие вопросы по тегам