StefanG
StefanG

Reputation: 269

How to show Master-Detail Informations in a collapsable ListView

I have a class that describes a certain task. This "task"-Class has a list of substeps.

What I wanted to do is to show these Informations in a ListView where the task-description should be used as the Groupheader and the substeps as the details

Also I wanted to be able to collapse and expand these groups.

Here is what I tried so far (simplified, but you'll get the idea hopefully):

public class Task : INotifyPropertyChanged
{
   public string Description;
   public ObservableCollection<String> substeps;
   ...
}

in the Viewmodel :

Task t = new Task();
t.Description = "Task1";
t.substeps.Add("substep 1");
t.substeps.Add("substep 2");
...

Tasks = new CollectionViewSource { Source = TaskList }; //TaskList is just a ObservableCollection<Task>
Tasks.GroupDescriptions.Add(new PropertyGroupDescription("Description"));

in xaml:

<s:SurfaceListBox Width="500" Height="1000" ItemsSource="{Binding TaskList.View}">
                <s:SurfaceListBox.Resources>
                    <Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <Expander Header="{Binding Description}" IsExpanded="True">
                                        <ItemsPresenter/>
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </s:SurfaceListBox.Resources>
                <s:SurfaceListBox.GroupStyle>
                    <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>
                </s:SurfaceListBox.GroupStyle>
                <s:SurfaceListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding substeps}"/>
                    </DataTemplate>
                </s:SurfaceListBox.ItemTemplate>
            </s:SurfaceListBox>

The Result is a Listbox with my collapsed item. If I expand it, instead of each step I only see "(Listing)"

Do I have to build a class with the substeps and the description in it, and group by the description?

Upvotes: 2

Views: 976

Answers (1)

Tri Q Tran
Tri Q Tran

Reputation: 5690

Try this:

<s:SurfaceListBox.ItemTemplate>
    <DataTemplate>
        <ItemsControl ItemsSource={Binding substeps} />
    </DataTemplate>
</s:SurfaceListBox.ItemTemplate>

Your problem is that the string binding to the ObservableCollection will just do a ToString() on that collection. You need iterate through the collection and display each item. By using the ItemsControl as I have done, you can also DataTemplate each subtask as you see fit.

ControlTemplate Binding

The Expander header binding will not work because it is inside a ControlTemplate which is inside the Style. The DataContext for the control template will not be your ViewModel but the control (i.e. SurfaceListBox) itself. Similar question is here.

There are two ways you can fix this.

1.Use DataTemplate

<s:SurfaceListBox.ItemTemplate>
    <DataTemplate>
        <Expander Header="{Binding Description}"
                  IsExpanded="True" >
            <ItemsControl ItemsSource={Binding substeps} />
        </Expander >
    </DataTemplate>
</s:SurfaceListBox.ItemTemplate>

2.Use TemplatedParent binding

<Expander Header="{Binding Content.Description, , RelativeSource={RelativeSource TemplatedParent}}"
          IsExpanded="True">

I personally recommend option 1.

Upvotes: 1

Related Questions