WPF - Warum Kontext-Menü-Einträge funktionieren mit den ListBox-aber nicht ItemsControl?
Elemente in einer Liste verfügen über ein Kontextmenü. Der Kontext-Menü-Elemente sind an Befehle weitergeleitet.
Kontext-Menü-Einträge funktionieren ordnungsgemäß, wenn das list-Steuerelement ist ein ListBox
, aber sobald ich downgrade es auf eine ItemsControl
es nicht mehr funktioniert. Speziell die Menüpunkte sind immer ausgegraut. Die CanExecute
Rückruf in meinem CommandBinding
wird nicht aufgerufen.
Was ist es über ListBox
ermöglicht Kontext-Menüelemente, Befehle zu binden, richtig?
Hier sind einige Auszüge aus einer Beispiel-app den ich zusammen gestellt habe zu markieren das problem:
<!-- Data template for items -->
<DataTemplate DataType="{x:Type local:Widget}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="UseWidget"
Command="{x:Static l:WidgetListControl.UseWidgetCommand}"
CommandParameter="{Binding}" />
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Price}" />
</StackPanel>
</DataTemplate>
<!-- Binding -->
<UserControl.CommandBindings>
<CommandBinding Command="{x:Static l:WidgetListControl.UseWidgetCommand}"
Executed="OnUseWidgetExecuted"
CanExecute="CanUseWidgetExecute" />
</UserControl.CommandBindings>
<!-- ItemsControl doesn't work... -->
<ItemsControl ItemsSource="{Binding Path=Widgets}" />
<!-- But change it to ListBox, and it works! -->
<ListBox ItemsSource="{Binding Path=Widgets}" />
Hier der C# - code für die view-Modell-und Daten-Element:
public sealed class WidgetListViewModel
{
public ObservableCollection<Widget> Widgets { get; private set; }
public WidgetViewModel()
{
Widgets = new ObservableCollection<Widget>
{
new Widget { Name = "Flopple", Price = 1.234 },
new Widget { Name = "Fudge", Price = 4.321 }
};
}
}
public sealed class Widget
{
public string Name { get; set; }
public double Price { get; set; }
}
Hier der C# code-behind für die Kontrolle:
public partial class WidgetListControl
{
public static readonly ICommand UseWidgetCommand
= new RoutedCommand("UseWidget", typeof(WidgetListWindow));
public WidgetListControl()
{
InitializeComponent();
}
private void OnUseWidgetExecuted(object s, ExecutedRoutedEventArgs e)
{
var widget = (Widget)e.Parameter;
MessageBox.Show("Widget used: " + widget.Name);
}
private void CanUseWidgetExecute(object s, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
}
Nur zu wiederholen, die Frage-was ist, ist, dass ListBox
bietet, die ermöglicht, dass es die Kontextmenü-Befehle zu binden, korrekt, und gibt es eine Möglichkeit, ich kann diese arbeiten für ItemsControl
?
- Beachten Sie, dass bei der Verwendung von ItemsControl, wenn ich definieren den CommandBindings direkt im Kontext-Menü dann funktioniert es, aber diese Niederlagen der Zweck der mit Hilfe der Befehle in den ersten Platz. Meine Vermutung ist, dass dies etwas hat zu tun mit ListBox-wrapping-Elemente in ListBoxItem-Objekte...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ok, das Hauptproblem, das ich sehe, ist, dass ein ItemsControl ist nicht ein Konzept, das ausgewählte Element, so können Sie nicht wählen Sie eine Position für das DataTemplate gebunden werden.
Ich kann mich nicht erinnern, wo ich es sah, aber eine gute Regel zu Folgen, beim schreiben von WPF ist, um das Steuerelement zu verwenden, dass Ihnen das Verhalten, das Sie brauchen, und dann Stil Sie Aussehen, was Sie wollen.
So denken über dies, Sie wollen das Verhalten einer ListBox, aber das Aussehen eines ItemsControl, also, warum nicht Sie Stil die ListBoxItems nicht zu zeigen, den Unterschied zwischen ausgewählten und nicht-ausgewählten.
Es ist wahrscheinlich auf die Tatsache zurückzuführen, dass Gegenstände in der ContextMenu-popup nicht int den gleichen visuellen Struktur als der rest deines UserControl (im Grunde popup ist ein separates Fenster). Das ist, warum die CommandBindings nicht funktionieren.
Aber jetzt habe ich nicht eine Idee wie man dieses Problem beheben, ohne zu definieren CommandBindings innerhalb des ContextMenu.