WPF: cómo aplicar el comando a un menú contextual de un cuadro de lista anidado

Estoy trabajando en una aplicación wpf usando PRISM. Esta es mi primera aplicación WPF y me he encontrado en una situación en la que no puedo seguir adelante.

Mi escenario es este, tengo una Lista de grupos que estoy vinculando con un ListBox, puede llamarlo ListBox principal, cada objeto de grupo tiene una lista de usuarios asociados y estoy vinculando esa lista con otro ListBox que está anidado en el cuadro de lista padre. Ambos enlaces funcionan bien, como se puede ver aquí:

enter image description here

Me enfrento a dos problemas.

1. Puedo seleccionar grupos y usuarios individuales dentro del grupo por separado, pero no están sincronizados, lo que significa que si selecciono un usuario, entonces el grupo que contiene este usuario no se selecciona. Intenté IsSynchronizedWithCurrentItem="True" pero parece que no funciona.

Agradecería mucho si alguien me puede señalar en la dirección correcta cómo lograr esto o si hay alguna otra forma además de usar ListBox dentro de ListBox.

2. Tengo un menú contextual asociado con ListBox principal y puedo vincular con éxito los comandos con los menús, pero tengo problemas para vincular comandos con el menú contextual de ListBox anidado, aquí está mi código

<ListBox x:Name="lstOfGroups" 
             ItemsSource="{Binding CurrentContest.Groups}"
             SelectedItem="{Binding SelectedGroup}"
             ItemTemplate="{StaticResource GroupTemplate}"
             Style="{StaticResource ListBoxStyle1}"
             ItemContainerStyle="{StaticResource ListBoxItemStyle1}"
             Background="Transparent" SelectionMode="Single"
             IsSynchronizedWithCurrentItem="True"
             Height="400">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal" Margin="5" Width="1200"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>

                <ListBox.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Add Contestant" Command="{Binding AddGroupCommand}"/>
                        <MenuItem Header="Edit Contestant" Command="{Binding EditGroupCommand}"/>
                        <MenuItem Header="Delete Contestant" Command="{Binding DeleteGroupCommand}"/>
                    </ContextMenu>
                </ListBox.ContextMenu>
            </ListBox>

<DataTemplate x:Key="GroupTemplate" >
        <Border x:Name="spPubItemBorder" Margin="3" BorderBrush="Black" BorderThickness="1" CornerRadius="10" Background="Honeydew">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <StackPanel Orientation="Horizontal">
                    <TextBlock Name="tbGroupName" Grid.Column="0" Style="{StaticResource ItemTextBox}">
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}Group Name: {0}">
                            <Binding Path="Name" />
                        </MultiBinding>
                    </TextBlock.Text>
                    </TextBlock>
                    <TextBlock Name="tbGroupAmount" Grid.Column="1" Style="{StaticResource ItemTextBox}">
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}Group Amount: {0}">
                            <Binding Path="Amount" />
                        </MultiBinding>
                    </TextBlock.Text>
                    </TextBlock>
                </StackPanel>
                <!--<ItemsControl ItemsSource="{Binding ContestantList}"
                              AlternationCount="2" ItemTemplate="{StaticResource ContestantTemplate}">

                </ItemsControl>-->
                <ListBox x:Name="lstOfContestant" Grid.Row="1"
                     ItemsSource="{Binding ContestantList}"
                     SelectedItem="{Binding SelectedContestant, ElementName=lstOfGroups}"
                     ItemTemplate="{StaticResource ContestantTemplate}"
                     Style="{StaticResource ListBoxStyleForContestant}"
                     ItemContainerStyle="{StaticResource ListBoxItemStyleForContestant}"
                     Background="Transparent" SelectionMode="Single"
                     Height="Auto">
                    <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel Orientation="Horizontal" Margin="5" Width="375"/>
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>

                    <ListBox.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Add Contestant" Command="{Binding Path=DataContext.AddContestantCommand,ElementName=contestantManager}"/>
                            <MenuItem Header="Edit Contestant" Command="{Binding Path=DataContext.EditContestantCommand,ElementName=contestantManager}"/>
                            <MenuItem Header="Delete Contestant" Command="{Binding Path=DataContext.DeleteContestantCommand,ElementName=contestantManager}"/>
                        </ContextMenu>
                    </ListBox.ContextMenu>
                </ListBox>

            </Grid>
        </Border>
    </DataTemplate>

Me preguntaba si alguien me puede señalar en la dirección correcta aquí también.

Gracias de antemano.

preguntado el 12 de junio de 12 a las 15:06

1 Respuestas

Para el n.° 1, configure el IsSelected propiedad del grupo ListBox a verdadero si IsKeyboardFocusWithin

<Style x:Key="GroupListBoxItemStyle" TargetType="ListBoxItem">
  <Style.Triggers>
    <Trigger Property="IsKeyboardFocusWithin" Value="True">
      <Setter Property="IsSelected" Value="True" />
    </Trigger>
  </Style.Triggers>
</Style>

Esto establecerá el grupo ListBoxItem como seleccionado cuando el enfoque del teclado está en cualquier lugar dentro de la ListBoxItem

En cuanto al n.° 2, parece que está obteniendo el elemento incorrecto, probablemente porque está usando ElementName en su encuadernación, sin embargo, el nombre se establece en varios elementos. Intenta usar un RelativeSource vinculante para encontrar el ContextMenu mismo, luego se une a la PlacementTarget.DataContext

<MenuItem Header="Add Contestant"
          Command="{Binding PlacementTarget.DataContext.AddContestantCommand, 
              RelativeSource={RelativeSource FindAncestor, 
              AncestorType={x:Type ContextMenu}}}" />

Respondido el 12 de junio de 12 a las 17:06

Gracias por la respuesta rápida, Rachel, agregar los disparadores de estilo parece haber funcionado, pero aún no puedo vincular los comandos al menú contextual con el código que proporcionaste anteriormente. - Saqib

@ user781466 El PlacementTarget devolverá cualquier objeto que tenga el ContextMenu, así que asegúrese de AddContestCommand existe en ese elemento DataContext. Es posible que deba hacer algo hackish para obtener el correcto DataContext, como vincular el Tag propiedad de ese elemento a la DataContext que tiene el comando que desea. Recomiendo usar una herramienta como Fisgón para saber cual es exactamente DataContext es que te unes a - Rachel

@user781466 En realidad acabo de notar su grupo ListBox es nombrado lstOfGroups mientras que los elementos de ContextMenu de tu concursante están vinculados a un ElementName=contestantManager. Intente cambiar el ElementName a lstOfGroups primero. - Rachel

Gracias, aunque cambiar ElementName a lstOfGroups no funcionó pero ha introducido una buena herramienta, voy a pasar un tiempo con ella e intentaré descubrir el DataContext del ListBox anidado. - Saqib

@user781466 Me alegro de haber podido ayudarte, buena suerte con tu proyecto :) Si mi respuesta te resultó útil o si respondió a tu pregunta, ¿te importaría votarla o aceptarla haciendo clic en la flecha hacia arriba junto a ella o en la marca de verificación? - Rachel

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.