web-dev-qa-db-fra.com

Menu contextuel WPF sur clic gauche

J'ai une application WPF..Dans laquelle j'ai un contrôle Image dans un fichier Xaml.

Sur le clic droit de cette image, j'ai un menu contextuel. 

Je voudrais avoir même pour être affiché sur "clic gauche" aussi.

Comment est-ce que je fais ceci de manière de MVVM?

23
Relativity

Voici une solution uniquement XAML… .. Il suffit d'ajouter ce style à votre bouton… .. Cela entraînera l'ouverture du menu contextuel par un clic gauche ou droit. Prendre plaisir!

<Button Content="Open Context Menu">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Click">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
                                    <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
                                </BooleanAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem />
                        <MenuItem />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>
38
Ben Wilde

Vous pouvez le faire en utilisant l'événement MouseDown d'une image comme ceci

<Image ... MouseDown="Image_MouseDown">
    <Image.ContextMenu>
        <ContextMenu>
            <MenuItem .../>
            <MenuItem .../>
        </ContextMenu>
    </Image.ContextMenu>
</Image>

Et ensuite, affichez le ContextMenu dans EventHandler dans le code derrière

private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ChangedButton == MouseButton.Left)
    {
        Image image = sender as Image;
        ContextMenu contextMenu = image.ContextMenu;
        contextMenu.PlacementTarget = image;
        contextMenu.IsOpen = true;
    }
}
11
Fredrik Hedblad

Vous pouvez inventer votre propre DependencyProperty qui ouvre un menu contextuel lorsque vous cliquez sur l'image, comme ceci:

  <Image Source="..." local:ClickOpensContextMenuBehavior.Enabled="True">
      <Image.ContextMenu>...
      </Image.ContextMenu>
  </Image>

Et voici un code C # pour cette propriété:

public class ClickOpensContextMenuBehavior
{
  private static readonly DependencyProperty ClickOpensContextMenuProperty =
    DependencyProperty.RegisterAttached(
      "Enabled", typeof(bool), typeof(ClickOpensContextMenuBehavior),
      new PropertyMetadata(new PropertyChangedCallback(HandlePropertyChanged))
    );

  public static bool GetEnabled(DependencyObject obj)
  {
    return (bool)obj.GetValue(ClickOpensContextMenuProperty);
  }

  public static void SetEnabled(DependencyObject obj, bool value)
  {
    obj.SetValue(ClickOpensContextMenuProperty, value);
  }

  private static void HandlePropertyChanged(
    DependencyObject obj, DependencyPropertyChangedEventArgs args)
  {
    if (obj is Image) {
      var image = obj as Image;
      image.MouseLeftButtonDown -= ExecuteMouseDown;
      image.MouseLeftButtonDown += ExecuteMouseDown;
    }

    if (obj is Hyperlink) {
      var hyperlink = obj as Hyperlink;
      hyperlink.Click -= ExecuteClick;
      hyperlink.Click += ExecuteClick;
    }
  }

  private static void ExecuteMouseDown(object sender, MouseEventArgs args)
  {
    DependencyObject obj = sender as DependencyObject;
    bool enabled = (bool)obj.GetValue(ClickOpensContextMenuProperty);
    if (enabled) {
      if (sender is Image) {
        var image = (Image)sender;
        if (image.ContextMenu != null)
          image.ContextMenu.IsOpen = true;
      }
    }
  } 

  private static void ExecuteClick(object sender, RoutedEventArgs args)
  {
    DependencyObject obj = sender as DependencyObject;
    bool enabled = (bool)obj.GetValue(ClickOpensContextMenuProperty);
    if (enabled) {
      if (sender is Hyperlink) {
        var hyperlink = (Hyperlink)sender;
        if(hyperlink.ContextMenu != null)
          hyperlink.ContextMenu.IsOpen = true;
      }
    }
  } 
}
7
slar

vous devez seulement ajouter le code dans la fonction Image_MouseDown

e.Handled = true;

Ensuite, il ne va pas disparaître.

3
Bruce Wu

vous pouvez lier la propriété Isopen du contextMenu à une propriété de votre viewModel telle que "IsContextMenuOpen" . mais le problème est que vous ne pouvez pas lier directement le contextmenu à votre viewModel car il ne fait pas partie de votre userControl hiarchy.So Pour résoudre ce problème, vous devez associer la propriété de balise au contexte dataontext de votre vue.

<Image Tag="{Binding DataContext, ElementName=YourUserControlName}">
<ContextMenu IsOpen="{Binding PlacementTarget.Tag.IsContextMenuOpen,Mode=OneWay}" >
.....
</ContextMenu>
<Image>

Bonne chance.

0
erradi mourad

Si vous voulez faire cela uniquement dans Xaml sans utiliser de code-behind, vous pouvez utiliser le support des déclencheurs d'Expression Blend:

...
xmlns:i="schemas.Microsoft.com/expression/2010/interactivity"
...

<Button x:Name="addButton">
    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding Items}" />
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=addButton, Mode=OneWay}"/>
                <ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="IsOpen" Value="True"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button.ContextMenu>
</Button>
0
Flatliner DOA

J'ai rencontré le même problème en cherchant une solution que je n'ai pas trouvée ici.

Je ne connais rien à MVVM, ce n'est donc probablement pas conforme à MVVM mais cela a fonctionné pour moi.

Étape 1: Donnez un nom à votre menu contextuel.

<Button.ContextMenu>
    <ContextMenu Name="cmTabs"/>
</Button.ContextMenu>

Étape 2: Double-cliquez sur l'objet de contrôle et insérez ce code. L'ordre compte!

Private Sub Button_Click_1(sender As Object, e As Windows.RoutedEventArgs)
        cmTabs.StaysOpen = True
        cmTabs.IsOpen = True
    End Sub

Étape 3: Profitez

Cela va réagir pour un clic gauche et droit. C'est un bouton avec ImageBrush avec un ControlTemplate.

0
Matthis Kohli