0
votes

In a view which contains an item having a collection of child items, I have an ItemsControl which hosts the child items collection. The individual items are contained in an Expander. When a child item is expanded, I need the parent view model to be aware of which child is being acted upon. I was able to implement an Event Trigger which passes the child object as a parameter to the parent view model, and the parent view model can then set a SelectedChildObject property. That is what I need but where it falls short is when multiple items are expanded, and the user acts on an item which is not in the most recently expanded item. When this happens the item they are interacting with does not match the SelectedChildObject property, since only the most recently expanded object would be the property value.

I have seen the solutions which use a ListBox to contain the Expander, and then set the Expander IsExpanded based on the ListBox IsSelected, but I don't like this solution because it only allows one expander open at a time, plus it does not seem possible to have the Expander stretch to fill all of the space in the ListBox, and this look does not look good.

Is there a way I can always let the parent view model know which child object is being acted upon?

<ItemsControl Grid.Row="0" Grid.Column="0"
                          ItemsSource="{Binding Slots, Mode=TwoWay}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Expander Padding="10">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Expanded">
                        <i:InvokeCommandAction Command="{Binding DataContext.ExpandedCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" CommandParameter="{Binding}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                <Expander.Header>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="32" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Image Grid.Row="0" Grid.Column="0"
                                           Height="16" Width="16" Source="/WpfApp1;component/Assets/Images/Warning.ico" />
                        <StackPanel Grid.Row="0" Grid.Column="1"
                                                Orientation="Horizontal">
                            <Label Content="Slot: " />
                            <Label Content="{Binding SlotNumber, Mode=TwoWay, ValidatesOnNotifyDataErrors=False}" />
                        </StackPanel>
                    </Grid>
                </Expander.Header>
                <StackPanel Margin="20">
                    <StackPanel Orientation="Horizontal">
                        <Label Content="Slot Number:" Margin="0 5 2 0" Width="100" />
                        <TextBox Text="{Binding SlotNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}" 
                                 Style="{DynamicResource Configuration.Input.TextBox}"
                                 Width="30" />
                    </StackPanel>

                    <StackPanel Orientation="Horizontal">
                        <Label Content="Modules:" Margin="0 5 2 0" Width="100" />
                        <ListBox ItemsSource="{Binding Source={x:Static local:SlotsViewModel.AllowedModules}}">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <CheckBox Content="{Binding}" 
                                              Command="{Binding DataContext.AddRemoveAllowedModuleCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" 
                                              CommandParameter="{Binding}"/>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </StackPanel>
                </StackPanel>
            </Expander>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
1

1 Answers

0
votes

What kind of actions are you trying to perform on Slots?

Something like removing the last manipulated slot? If so then you will probably have to write a behavior or a control that will capture PreviewMouseDown events and send a command/event to notify your parent View Model. But it's not ideal.

And any way you will probably want the "Selected slot" to be highlighted befor it can be removed. You could also try to remove background of the expander and use the ListBox. So that when you click on the background of your Slot it selects and highlights the ListBoxItem. In this way you can bind SelectedItem to the VM.