Frage

Interessantes Problem in Bezug auf Befehle aus dem Kontextmenüpunkt Brennen ...

Ich möchte einen Befehl feuern eine Zeile in meiner Kontrolle einzufügen, InsertRowCmd. Dieser Befehl muss wissen, wo die Zeile einzufügen.

Ich konnte verwenden Mouse.GetPosition (), aber das würde mir die Position der Maus erhält zur Zeit, die sie über den Menüpunkt wäre. Ich mag stattdessen den Ursprung des Kontextmenüs erhalten.

Hat jemand irgendwelche Vorschläge, wie die Herkunft des Kontextmenüs als Parameter an den Befehl übergeben?

Beispielcode:

<UserControl x:Name="MyControl">
<!--...-->
        <ContextMenu x:Name="menu">
            <MenuItem Header="Insert Row" Command="{x:Static customCommands:MyCommands.InsertRowCmd}" CommandParameter="?"/>
        </ContextMenu>
</UserControl>

Meine aktuellen Ideen sind wie folgt:

-Use klicken Handler statt, so dass ich den Ursprung in Code zu finden. Das Problem ist, dass ich dann zu behandeln habe die Aktivierung / Deaktivierung.

-Handle Click-Ereignis und den Ursprung des Kontextmenüs speichern. Geben Sie diese gespeicherten Informationen in den Befehl. Ich habe, dass die Click-Ereignisse Feuer überprüft, bevor der Befehl ausgeführt wird.

Irgendwelche Ideen?

EDIT:

Ich bin mit Josh Smith CommandSinkBinding Route den Befehl in meine Viewmodel Klasse Handhabung. So ist der Code, der die Befehlsausführung Griffe weiß nichts über die Aussicht.

War es hilfreich?

Lösung

Sie werden verwenden müssen TranslatePoint die obere linke (0, 0) des ContextMenu einer Koordinate in dem Gitter enthalten, zu übersetzen. Sie könnten dies tun, indem Sie die CommandParameter zum ContextMenu Bindung und einen Konverter verwenden:

CommandParameter="{Binding IsOpen, ElementName=_menu, Converter={StaticResource PointConverter}}"

Ein weiterer Ansatz wäre ein angebaute Verhalten sein, das eine angeschlossene Nur-Lese-Eigenschaft vom Typ Point automatisch aktualisiert, sobald die ContextMenu geöffnet werden. Verbrauch würde wie folgt aussehen:

<ContextMenu x:Name="_menu" local:TrackBehavior.TrackOpenLocation="True">
    <MenuItem Command="..." CommandParameter="{Binding Path=(local:TrackBehavior.OpenLocation), ElementName=_menu}"/>
</ContextMenu>

So ist die TrackOpenLocation angebracht Eigenschaft macht die Arbeit mit dem ContextMenu für die Befestigung und eine zweite angefügten Eigenschaft (OpenLocation) aktualisiert, wenn der ContextMenu geöffnet wird. Dann kann die MenuItem nur binden an OpenLocation die Lage zu bekommen, an dem die ContextMenu zuletzt geöffnet wurde.

Andere Tipps

Im Anschluss an Kent Antwort, habe ich seinen angefügten Eigenschaft Vorschlag und endete mit diesem (mit Josh Smith Beispiel für angebracht Verhalten ):

public static class TrackBehavior
{
 public static readonly DependencyProperty TrackOpenLocationProperty = DependencyProperty.RegisterAttached("TrackOpenLocation", typeof(bool), typeof(TrackBehavior), new UIPropertyMetadata(false, OnTrackOpenLocationChanged));

 public static bool GetTrackOpenLocation(ContextMenu item)
 {
  return (bool)item.GetValue(TrackOpenLocationProperty);
 }

 public static void SetTrackOpenLocation(ContextMenu item, bool value)
 {
  item.SetValue(TrackOpenLocationProperty, value);
 }

 public static readonly DependencyProperty OpenLocationProperty = DependencyProperty.RegisterAttached("OpenLocation", typeof(Point), typeof(TrackBehavior), new UIPropertyMetadata(new Point()));

 public static Point GetOpenLocation(ContextMenu item)
 {
  return (Point)item.GetValue(OpenLocationProperty);
 }

 public static void SetOpenLocation(ContextMenu item, Point value)
 {
  item.SetValue(OpenLocationProperty, value);
 }

 static void OnTrackOpenLocationChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
 {
  var menu = dependencyObject as ContextMenu;
  if (menu == null)
  {
   return;
  }

  if (!(e.NewValue is bool))
  {
   return;
  }

  if ((bool)e.NewValue)
  {
   menu.Opened += menu_Opened;

  }
  else
  {
   menu.Opened -= menu_Opened;
  }
 }

 static void menu_Opened(object sender, RoutedEventArgs e)
 {
  if (!ReferenceEquals(sender, e.OriginalSource))
  {
   return;
  }

  var menu = e.OriginalSource as ContextMenu;
  if (menu != null)
  {
   SetOpenLocation(menu, Mouse.GetPosition(menu.PlacementTarget));
  }
 }
}

und dann in der XAML zu verwenden, müssen Sie nur:

<ContextMenu x:Name="menu" Common:TrackBehavior.TrackOpenLocation="True">
 <MenuItem Command="{Binding SomeCommand}" CommandParameter="{Binding Path=(Common:TrackBehavior.OpenLocation), ElementName=menu}" Header="Menu Text"/>
</ContextMenu>

Allerdings habe ich auch benötigt, um hinzuzufügen:

NameScope.SetNameScope(menu, NameScope.GetNameScope(this));

an den Konstruktor meiner Meinung nach, sonst wird die Bindung für das CommandParameter nicht ElementName=menu Nachschlag könnte.

Neben Kent Antwort, denkt über einen „normalen Weg“. F. E. wenn ein ListBox ein ContextMenu hat, brauchen Sie nicht Menü Position, weil das ausgewählte Element gesetzt wird, bevor das Menü aufgetaucht. Also, wenn Ihr Steuer wäre etwas, das „ausgewählte“ auf der rechten Seite klicken wird ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top