2

So I got a view which one got a listView. This ListView got an ItemSource "Persons" and this list view I got some some CheckBox.

When a CheckBox is checked I want to execute a command "CanStartRaceCheckCommand" from my ViewModel "RaceSimulatorViewModel".

But that doesn't work because the program try to get a command from my class Person.

So there are some errors of bindings.

Can you please help me?

I have tried this solution : WPF MVVM: EventTrigger is not working inside CheckBox

There is the Xaml :

<ListView ItemsSource="{Binding Persons}" Grid.Row="1" Margin="40,100,367,46" Grid.RowSpan="3" Grid.ColumnSpan="2"  >
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Full Name"  DisplayMemberBinding="{Binding Path=Name}"/>
            <GridViewColumn Header="Participe to race" >
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <!--<CheckBox IsChecked="{Binding Path=IsParticipateToRace}" Command="{Binding CanStartRaceCheckCommand, RelativeSource={RelativeSource AncestorType={x:Type vm:RaceSimulatorViewModel}, AncestorLevel=1}}"></CheckBox>-->
                        <!--<CheckBox Command="{Binding CanStartRaceCheckCommand}" CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}" />-->
                        <CheckBox IsChecked="{Binding Path=IsParticipateToRace}"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

and there is my output:

System.Windows.Data Error: 40 : BindingExpression path error: 'CanStartRAceCheckCommand' property not found on 'object' ''Person' (HashCode=43304686)'. BindingExpression:Path=CanStartRAceCheckCommand; DataItem='Person' (HashCode=43304686); target element is 'CheckBox' (Name=''); target property is 'Command' (type 'ICommand')

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • You have similar question here https://stackoverflow.com/questions/1511516/bind-to-itemscontrols-datacontext-from-inside-an-itemtemplate – Dmitry Dec 25 '18 at 22:37
  • I tried tried that : System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='RaceSimulator.ViewModel.RaceSimulatorViewModel', AncestorLevel='1''. BindingExpression:Path=DataContext.CanStartRaceCheckCommand; DataItem=null; target element is 'CheckBox' (Name=''); target property is 'Command' (type 'ICommand') – keust keust Dec 26 '18 at 00:02

1 Answers1

2

The markup extension 'RelativeSource' is used to bind to an object outside the DataContext. In contrast to the 'StaticResource' extension, it applies to the 'RelativeSource' Binding property instead of the 'Source' property. It can be used to traverse the visual tree. Keep in mind that you are creating a tree of elements. 'RelativeSource' allows you to traverse this tree back to the root element and select one visited element as binding source by passing the target element's type and the relative tree level. It's similar to setting the 'Source' property on a Binding object, where you would specify the data source. The data itself or the path to the data on that source is set by the 'Path' property of the Binding.

You will have to traverse the tree until you find an element that exposes the proper data. In your case the required data source of the binding is the ListView (which is outside your default data context --> a relative source). The ListViewexposes the data RaceSimulatorViewModel via the 'DataContext'.

So

Command="{Binding DataContext.CanStartRaceCheckCommand, RelativeSource={RelativeSource AncestorType={x:Type vm:RaceSimulatorViewModel}, AncestorLevel=1}}"

becomes

Command="{Binding DataContext.CanStartRaceCheckCommand, RelativeSource={RelativeSource AncestorType=ListView}}"

In general the data context is inherited by child elements. For templates (ControlTemplate, DataTemplate) this is slightly different. As the template names suggest the ControlTemplate is used to describe a control and the DataTemplate to describe data (or how it is visualized). Therefore the data context of a ControlTemplate is the templated control whereas the data context of a DataTemplate is the templated data (in your case the Person data object). This makes it possible to base visuals on the state of the data, e.g. 'Person.Age' < 18 --> draw it red. ControlTemplate in contrast is basically based on control state, e.g. CheckBox.IsChecked? --> change visibility of some other control.

BionicCode
  • 1
  • 4
  • 28
  • 44