Wpf Expander Collection, как сделать так, чтобы родительский ViewModel знал, какой объект Expander является текущим?

В представлении, которое содержит элемент, имеющий коллекцию дочерних элементов, у меня есть ItemsControl, который содержит коллекцию дочерних элементов. Отдельные предметы содержатся в Expander. Когда дочерний элемент раскрывается, мне нужно, чтобы модель родительского представления знала, над каким дочерним элементом выполняется действие. Мне удалось реализовать триггер события, который передает дочерний объект в качестве параметра в модель родительского представления, а затем модель родительского представления может установить свойство SelectedChildObject. Это то, что мне нужно, но в чем-то не хватает, когда раскрываются несколько элементов, и пользователь воздействует на элемент, которого нет в последнем расширенном элементе. Когда это происходит, элемент, с которым они взаимодействуют, не соответствует свойству SelectedChildObject, поскольку значением свойства будет только последний развернутый объект.

Я видел решения, которые используют ListBox, чтобы содержать Expander, а затем установить Expander IsExpanded на основе ListBox IsSelected, но мне не нравится это решение, потому что оно позволяет открывать только один расширитель за раз, плюс оно не кажется возможно иметь растяжку Expander, чтобы заполнить все пространство в ListBox, и этот внешний вид выглядит не очень хорошо.

Есть ли способ, которым я всегда могу сообщить модели родительского представления, на какой дочерний объект воздействуют?

<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 ответ

Какие действия вы пытаетесь выполнить в слотах?

Что-то вроде удаления последнего манипулируемого слота? Если это так, то вам, вероятно, придется написать поведение или элемент управления, который будет захватывать события PreviewMouseDown и отправлять команду / событие для уведомления вашей родительской модели представления. Но это не идеально.

И в любом случае вы, возможно, захотите выделить "Выбранный слот", прежде чем его можно будет удалить. Вы также можете попробовать удалить фон экспандера и использовать ListBox. Так что, когда вы нажимаете на фон вашего слота, он выбирает и выделяет ListBoxItem. Таким образом, вы можете привязать SelectedItem к виртуальной машине.

Другие вопросы по тегам