1
votes

I am trying to create a view that holds a ListBox that its ItemsSource property is bound to an ObservableCollection and its ItemTemplate property is bound to another property. I know it is unclear, so I will add some code...

This code is the relevant section from my markup:

<ListBox ItemsSource="{Binding MyCollection}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding FirstName}" Height="{Binding Path=Index, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindowViewModel}}}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

('FirstName' is a property of Person type, which is the type parameter of my collection. I wont add the code for that class because it is very intuitive) The code-behind of the view sets the DataContext to hold a reference to and instance of this ViewModel class:

public class MainWindowViewModel : INotifyPropertyChanged
{
    int index;
    ObservableCollection<Person> myCollection;

    public ObservableCollection<Person> MyCollection
    {
        get 
        {
            if (myCollection == null)
            {
                //create the collection - not relevant for my question
            }
            return myCollection;
        }
    }
    public int Index
    {
        get
        {
            //calculate value...
        }
        set
        {
            //set the value...
        }
    }

Since I bind the ItemsSource to the collection, I find it hard to bind to properties in my ViewModel (I manage to bind simply Person's properties...), and my code gives me binding error in the output window:

Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='SimpleMVVM.MainWindowViewModel', AncestorLevel='1''. BindingExpression:Path=Index; DataItem=null; target element is 'Button' (Name=''); target property is 'Height' (type 'Double')

Can someone please help me figure that out? (btw - sorry for the poor title, I just couldnt find anything clearer)

2

2 Answers

4
votes

The Index property will be located in the ListBox DataContext so change the Height Binding to the following and it should work

Height="{Binding Path=DataContext.Index,
                 RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/>

For the ListBox

<ListBox ItemsSource="{Binding MyCollection}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding FirstName}"
                    Height="{Binding Path=DataContext.Index,
                                     RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/>  
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
1
votes

You need to set the DataContext of the height binding to the viewmodel the way it is now it is looking for the index property on the individual data items in the collection