Привязка данных иерархического объекта к ListBox - PullRequest
1 голос
/ 14 мая 2011

Я пытаюсь заполнить ListBox данными из источника объекта, используя привязку данных в WPF.

Источником является ObjectDataProvider, данные которого загружаются из файла XML. Я прочитал в файле XML, заполнив соответствующую структуру данных, а затем установил ObjectInstance для ObjectDataProvider в структуру данных.

Вот структура данных:

public class Element
{
       public decimal myValue;

       public decimal df_myValue { get { return myValue; } set { this.myValue = value; } }
}

public class BasicSet
{
       public Element[] elementSet;

       public Element[] df_elementSet { get { return elementSet; } set { this.elementSet = value; } }
}

public class DataSet
{
        public BasicSet[] basicSet;

    public BasicSet[] df_basicSet { get { return basicSet; } set { this.basicSet = value; } }
}

Вот XAML:

<UserControl.Resources>
    <ResourceDictionary>
        <ObjectDataProvider x:Key="TheData" />

        <DataTemplate x:Key="ElementTemplate">
            <StackPanel>
                <TextBox Text="{Binding, Path=df_myValue}" />
            </StackPanel>
        </DataTemplate>

        <HierarchicalDataTemplate x:Key="ElementSetTemplate" ItemsSource="{Binding Path=df_elementSet}" ItemTemplate="{StaticResource ElementTemplate}">
        </HierarchicalDataTemplate>

    </ResourceDictionary>
</UserControl.Resources>

<Grid>
    <ListBox ItemsSource="{StaticResource TheData}" ItemTemplate="{StaticResource ElementSetTemplate}">
    </ListBox>
</Grid>

Вот код, в который загружаются данные XML:

    private DataSet m_dataSet;
    private ObjectDataProvider mODP;

    public void LoadXml(EditorContext context, XmlValidator.Context validator, XmlDocument doc)
    {
        mODP = FindResource("TheData") as ObjectDataProvider;

        XmlSerializer xs = new XmlSerializer(typeof(DataSet));
        XmlReader r = new XmlNodeReader(doc.DocumentElement);
        m_dataSet = (DataSet)xs.Deserialize(r);

        mODP.ObjectInstance = m_dataSet;
    }

Желаемый результат состоит в том, что ListBox будет иметь TextBox для каждого элемента в структуре данных. Обратите внимание, что структура данных является иерархической по причине. Я не могу сгладить структуру данных, чтобы упростить проблему.

Я уверен, что данные XML правильно загружаются в структуру данных, потому что я могу установить точку останова и проверить ее, и все данные выглядят нормально. Но когда я запускаю программу, в ListBox ничего не появляется.

Любая помощь приветствуется.

1 Ответ

4 голосов
/ 15 мая 2011

Я понял, что я делаю неправильно. Было несколько вещей не так. Вот основные моменты:

1) Я должен был использовать itemsControl

2) Мне не нужно было использовать HierarchicalDataTemplate

3) Мне потребовалось три уровня элементов управления: TextBox внутри itemsControl внутри itemsControl ... и это можно сделать с помощью двух DataTemplates. ItemsControl верхнего уровня ссылается на DataTemplate, который содержит внутренний itemsControl. Затем itemsControl ссылается на DataTemplate, который содержит внутренний TextBox.

А вот правильный xaml:

<UserControl.Resources>
    <ResourceDictionary>
        <ObjectDataProvider x:Key="TheData" />

        <DataTemplate x:Key="ElementTemplate">
            <TextBox Text="{Binding Path=df_myValue}"/>
        </DataTemplate>

        <DataTemplate x:Key="ElementSetTemplate">
            <GroupBox Header="I am a GroupBox">
                <ItemsControl ItemsSource="{Binding Path=df_elementSet}" ItemTemplate="{StaticResource ElementTemplate}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </GroupBox>
        </DataTemplate>

    </ResourceDictionary>
</UserControl.Resources>

<Grid>
    <ItemsControl ItemsSource="{Binding Source={StaticResource TheData}, Path=df_basicSet}" ItemTemplate="{StaticResource ElementSetTemplate}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid>

Надеюсь, это поможет кому-то еще ...

...