wpf mvvm contextmenu mouseleftbuttondown

Menú contextual de WPF a la izquierda



mvvm contextmenu (8)

Aquí hay una única solución XAML. Simplemente añada este estilo a su botón. Esto hará que el menú contextual se abra con los botones izquierdo y derecho. ¡Disfrutar!

<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>

Tengo una aplicación WPF ... En la cual tengo un control de imagen en un archivo Xaml.

En el botón derecho de esta imagen tengo un menú contextual.

Me gustaría que se muestre lo mismo en "Clic izquierdo" también.

¿Cómo hago esto de manera MVVM?


Hola, encontré el mismo problema buscando una solución que no encontré aquí.

No sé nada acerca de MVVM, así que probablemente no sea compatible con MVVM pero funcionó para mí.

Paso 1: Dale un nombre a tu menú contextual.

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

Paso 2: Haga doble clic en el objeto de control e inserte este código. ¡La orden importa!

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

Paso 3: Disfruta

Esto reaccionará para clic izquierdo y derecho. Es un botón con un ImageBrush con un ControlTemplate.


Puede inventar su propia propiedad de dependencia, que abre un menú de contexto cuando se hace clic en la imagen, así:

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

Y aquí hay un código C # para esa propiedad:

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; } } } }


Puedes hacer esto usando el evento MouseDown de una imagen como esta

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

Y luego muestre el ContextMenu en el EventHandler en el código detrás

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; } }


Si desea hacer esto solo en Xaml sin usar el código subyacente, puede usar el soporte de activación de 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>


XAML

<Button x:Name="b" Content="button" Click="b_Click" > <Button.ContextMenu > <ContextMenu > <MenuItem Header="Open" Command="{Binding OnOpen}" ></MenuItem> <MenuItem Header="Close" Command="{Binding OnClose}"></MenuItem> </ContextMenu> </Button.ContextMenu> </Button>

DO#

private void be_Click(object sender, RoutedEventArgs e) { b.ContextMenu.DataContext = b.DataContext; b.ContextMenu.IsOpen = true; }


puede vincular la propiedad Isopen del contextMenu a una propiedad en su viewModel como "IsContextMenuOpen". pero el problema es que no puede enlazar directamente el menú contextual a su viewModel porque no es parte de su control de usuario. Por lo tanto, para resolver esto, debe colocar la propiedad de la etiqueta en el contexto de datos de su vista.

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

Buena suerte.


solo necesita agregar el código en la función Image_MouseDown

e.Handled = true;

Entonces no desaparecerá.