Binding do CommandParameter wewnątrz menu kontekstowego wyświetlanego dla każdego elementu listy

0

Jak przekazać ListBox.SelectedIndex do MenuItem.CommandParameter wewnątrz ContexMenu bez dodawania SelectedIndex do view modelu?

public ObservableCollection<string> SelectedWords { get; set; };
public ICommand DeleteWordCommand { get; }

public ViewModel()
{
  DeleteWordCommand = new RelayCommand<int>(HandleWordDeletion);
}

private void HandleWordDeletion(int selectedIndex)
<ListBox ItemsSource="{Binding SelectedWords}">
    <ListBox.InputBindings>
        <KeyBinding Key="Delete" Command="{Binding DeleteWordCommand}" CommandParameter="{Binding SelectedIndex, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}" />
    </ListBox.InputBindings>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Tag" Value="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=ListBox}}" />
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu Tag="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                        <MenuItem Header="Delete"
                          Command="{Binding PlacementTarget.Tag.DeleteWordCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
                          CommandParameter=""
                          />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

1

Wkleiłem Twój post do ChatGPT, odpowiedz poniżej, u mnie działa ;)
PS. Przy okazji dzięki za patent z ContextMenu na liście, sporo mi ułatwia :)


Aby przekazać wartość SelectedIndex z ListBox do CommandParameter w MenuItem bez użycia view modelu, możesz użyć BindingProxy.

Najpierw utwórz klasę BindingProxy, która będzie przechowywać wybrany indeks z ListBox:

public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
}

Dodaj BindingProxy do zasobów w XAML:

<ListBox.Resources>
    <local:BindingProxy x:Key="proxy" Data="{Binding SelectedIndex, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}" />
</ListBox.Resources>

Ustaw CommandParameter w MenuItem na BindingProxy:

<ContextMenu Tag="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
    <MenuItem Header="Delete"
        Command="{Binding PlacementTarget.Tag.DeleteWordCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
        CommandParameter="{Binding Data, Source={StaticResource proxy}}"
        />
</ContextMenu>

Teraz, gdy klikniesz prawym przyciskiem myszy na element ListBox, ContextMenu będzie miała dostęp do SelectedIndex i przekaże go do DeleteWordCommand jako parametr.

1 użytkowników online, w tym zalogowanych: 0, gości: 1