2010-11-29 41 views
19

Tengo una aplicación WPF ... En la que tengo un control de imagen en el archivo Xaml.WPF Menú de contexto en el botón izquierdo

Al hacer clic con el botón derecho de esta imagen, tengo un menú contextual.

Me gustaría que el mismo se muestre en "clic izquierdo" también.

¿Cómo hago esto en modo MVVM?

+1

Aunque es posible, sería un error si se visualizan las ventanas estándar con un clic izquierdo. –

+0

Pero mi cliente necesita eso – Relativity

+0

En cuanto a hacer este MVVM, creo que XAML estaría en su "vista", el código Image_MouseDown C# estaría en su "modelo de vista", y su "modelo" no debería saber nada sobre el menú contextual . –

Respuesta

11

Usted puede hacer esto mediante el evento MouseDown de una imagen como esta

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

Y luego mostrar el ContextMenu en el manejador de sucesos 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; 
    } 
} 
+5

Esta implementación hace que el menú contextual aparezca e inmediatamente desaparezca. Estoy usando el control y su menú de contexto en un DataTemplate, no estoy seguro si eso importa ... – epalm

+0

esto no parece levantar el evento ContextMenuOpening así que el código depende de eso no se ejecutará ... – stijn

+0

Veo lo mismo que epalm – Rhyous

0

Si quieres hacer esto solo en Xaml sin usar código subyacente, puede usar el soporte de disparadores 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> 
+0

¿Podría especificar los espacios de nombres xml en su ejemplo? – jan

+0

xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: i = "http://schemas.microsoft.com/expression/2010/interactivity" –

+0

Esto tiene el mismo problema epalm menciona en la otra respuesta – Rhyous

3

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

e.Handled = true;

Entonces no desaparecerá.

31

Aquí hay una solución única de XAML. Simplemente agregue este estilo a su botón. Esto hará que el menú contextual se abra en el clic 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> 
+0

No funciona la propiedad para net35 –

+7

El estilo fue correcto, sin embargo, cuando agregué Comando a MenuItem, no desencadenó el evento. He verificado - las fijaciones son correctas. ¿Alguna idea? – utkarsh

0

se puede obligar a la propiedad de la IsOpen contextMenu a una propiedad en su modelo de vista como "IsContextMenuOpen". pero el problema es que no puede enlazar directamente el menú contextual a su viewModel porque no es una parte de su hiarchy userControl. Así que para resolver esto, debe agregar la propiedad de la etiqueta al dataontext de su vista.

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

Buena suerte.

6

Puede inventar su propio DependencyProperty que se abre un menú contextual al hacer clic en la imagen, al igual que este:

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

Y aquí es 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; 
     } 
    } 
    } 
} 
+1

Esto fue muy útil, pero necesitaba asignar el 'PlacementTarget' del' ContextMenu' de vuelta al 'DependencyObject' (en mi caso,' Button'), para que el menú se llenara correctamente. Esto fue para un menú contextual dinámico poblado para cada elemento en un 'ListView'. –

-1

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> 

C#

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

OP pregunta por un clickevent en un control de imagen. Está sirviendo una solución para un control de botón. –

+0

Esto tampoco sigue las buenas prácticas de mvvm. –

0

Oye me encontré con el mismo problema buscando una solución que no encontré aquí.

No sé nada de MVVM por lo que probablemente no sea MVVM pero me funcionó.

Paso 1: Asigne un nombre al menú contextual.

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

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

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

Paso 3: Disfrute de

Esta reaccionará para la izquierda & clic derecho. Es un botón con ImageBrush con ControlTemplate.

Cuestiones relacionadas