blueeyes
blueeyes

Reputation: 59

XAML ListView in ListView

Is it possible to make a ListViewin a ListView and if yes is it even possible to bind data in both of them? I already tried it but it wont work the first List is shown as i want but the second is not shown.

The Code Looks kind of like this:

<ListView ItemSource="{Binding Item}" x:Name="ListA">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock Text="{Binding Day}"/>
                <ListView x:Name="ListB" ItemSoruce="{Binding Item}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Time}"/>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

C#

listA.ItemsSource = timebooking.TimeBookingDataPeriod.TimeBookingData;

Hope sombody can help me :)

Upvotes: 1

Views: 2146

Answers (2)

Bart
Bart

Reputation: 10015

First of all, you should either go for a binding ItemSource={Binding Item} or setting the ItemSource in code listA.ItemsSource = ... as one overwrites the other. So I'll ignore the fact that you're trying to set it in code and go with the binding (which means you have a datacontext set on your view).

<ListView ItemSource="{Binding WeekDays}" x:Name="ListA">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock Text="{Binding Day}"/>
                <ListView x:Name="ListB" ItemSource="{Binding TimesOfDay}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Time}"/>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

I've changed your first ItemSource to WeekDays and the second ItemSource to TimesOfDay for clarity. This to explain the way how binding and datacontexts work.

  • The outer ListView (ListA) inherits its DataContext from the outer items, most likely your page / usercontrol.
  • In your ListViewItem, the datacontext is changed to a single item in the WeekDays collection. => every property bound under this tree has to be in a WeekDay object.
  • The inner ListView (ListB) inherits its DataContext from the ListViewItem.
  • In the ListViewItem, the DataContext is changed to a single item in the TimesOfDay collection.

Every ListView is a new level of objects. So for my sample to work, you need following class structure, not that I'll simplify the code and just use properties (while you should correctly implement INotifyPropertyChanged for UI updates).

public class SampleViewModel : INotifyPropertyChanged
{
    public ObservableCollection<WeekDay> WeekDays { get; set; } // first listview
}

public class WeekDay
{
    public string Day { get; set; }
    public ObservableCollection<TimeOfDay> TimesOfDay { get; set; } // second listview
}

public class TimeOfDay
{
    public string Time { get; set; }
}

If you want to use 2 properties from the page's viewmodel, you'll have to use an element binding in ListB. But this is only for scenarios were the items in the inner listview are not correlated to the ones in the outer listview.

{Binding ElementName=ListA, Path=DataContext.ItemsForB}

Upvotes: 2

Sergiu Cojocaru
Sergiu Cojocaru

Reputation: 687

  1. ItemsSource not ItemSource
  2. Here is an example:

    public class ClassB
        {
            public string Name { get; set; }
            public ObservableCollection<ClassA>classAList { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="ClassB"/> class.
            /// </summary>
            public ClassB()
            {
                Name = String.Empty;
                classAList = new ObservableCollection<ClassA>();
    
            }
        }
    

    public class ClassA { public string Caption { get; set; } }

Create list:

ObservableCollection<ClassB> list = new ObservableCollection<ClassB>();

Init list:

ClassB item1 = new ClassB() { Name = "listAItem1" };
            item1.classAList.Add(new ClassA { Caption = "listBItem1" });
            item1.classAList.Add(new ClassA { Caption = "listBItem2" });
            item1.classAList.Add(new ClassA { Caption = "listBItem3" });
            item1.classAList.Add(new ClassA { Caption = "listBItem4" });
            item1.classAList.Add(new ClassA { Caption = "listBItem5" });

            list.Add(item1);


            ClassB item2 = new ClassB() { Name = "listAItem1" };
            item2.classAList.Add(new ClassA { Caption = "listBItem1" });
            item2.classAList.Add(new ClassA { Caption = "listBItem2" });
            item2.classAList.Add(new ClassA { Caption = "listBItem3" });
            item2.classAList.Add(new ClassA { Caption = "listBItem4" });
            item2.classAList.Add(new ClassA { Caption = "listBItem5" });

            list.Add(item1);

            this.DataContext = list;

and XAML:

<ListView ItemsSource="{Binding}" x:Name="ListA">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="Day"/>
                        <ListView x:Name="ListB" ItemsSource="{Binding classAList}">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Caption}"/>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
  1. It seems you want to create a grouped list, in this case is better to use gridview with groups: Good step by step tutorial for grouped gridview

Upvotes: 0

Related Questions