SumGuy
SumGuy

Reputation: 491

Binding a collection to comboboxes within a listview

Ok so, I have a listview with several rows which is defined by setting the itemsource in the code. Within each row that's generated I have a combobox. In the code I have another array of objects which is the collection that this combobox should display.

I basically want it so that for each row you can select an option from the list. The list of possibilities will always be the same, hence the array.

A little bit of code to help. This is what I have for XAML:

    <ListView Name="lvVanList">
        <ListView.View>
            <GridView>
                <DisplayMemberBinding="{Binding Path=Number}">Van</GridViewColumn>
                <GridViewColumn Header="Rooms">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <ComboBox Name="cbSchemeList" ItemsSource="{Binding Path=_RoomList}" SelectedValue="{Binding Path=Room}" DisplayMemberPath="Name" />
                            </StackPanel>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

The code behind:

    private RoomList _RoomList;

    public populateList()
    {
        this.lvVanList.ItemsSource = this.getVans;
        this._RoomList = this.getRooms;
    }

    private class Room
    {
        string Name { get; set; }
        int Windows { get; set; } 
    }

Unfortunately this shows a blank list when the combobox is open.

I do have a way around this by storing the possibilities list in the object which is binded to each row but I'm sure I should be able to just use a single collection.

It's tough to describe so if there's any information I've missed or it's not understandable please let me know.

Thanks in advance

Upvotes: 1

Views: 4588

Answers (3)

Haris Hasan
Haris Hasan

Reputation: 30107

Try this

<ComboBox Name="cbSchemeList"  ItemsSource="{Binding RelativeSource={RelativeSource
    FindAncestor, AncestorType={x:Type ViewModel}},
    Path=RoomList }" SelectedValue="{Binding Path=Room}" />

Here ViewModel is what contains your RoomList property

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174447

The problem is that the binding path (_RoomList) is relative to the DataContext of each entry of the ListView. And that DataContext is the displayed item and not your view.

You can solve this in multiple ways:

  1. Put the list in the displayed items - that's what you already discovered and want to avoid
  2. Give your view a name and use that name the binding as ElementName
  3. In the binding, find the ancestor of the item that is the view

Upvotes: 1

Samuel Slade
Samuel Slade

Reputation: 8623

My guess is that the DataContext of each row of the ListView is going to be the item that that row of the ListView is bound to. So, when binding to the _RoomList property, it is trying to bind to that on each item.

Instead, you need to point the _RoomList binding to the element containing that property. For example, if it's in the MainWindow, you would add the attribute x:Name="This" to MainWindow, then change your binding to be ItemsSource={Binding ElementName=This, Path=_RoomList}.

An example of how you could approach it would be (using a modified version of your code):

<Window x:Class="ComboBoxListViewBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="This"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <ListView Name="lvVanList">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Number}">Van</GridViewColumn>
                    <GridViewColumn Header="Rooms">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <ComboBox Name="cbSchemeList" ItemsSource="{Binding Path=RoomList}" SelectedValue="{Binding Path=Room}" />
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>

            <TextBlock Text="Testing" />
            <TextBlock Text="Testing" />
            <TextBlock Text="Testing" />
        </ListView>
    </Grid>
</Window>

Upvotes: 0

Related Questions