Astuces DotNet (Sébastien Courtois)

25/01/2010

[Silverlight 4] Supprimer le context menu “Silverlight” lors d’un clic droit

Filed under: Débutant, Silverlight 4, XAML — Étiquettes : , , , , , — sebastiencourtois @ 22:41

Silverlight 4 apporte une nouveauté très demandée : La gestion du clic droit. Le problème est que, par défaut, le clic droit s’accompagne d’un menu contextuel “Silverlight” un peu énervant. Toutefois, il y a une manière de s’affranchir de celui-ci.

L’évènement MouseRightButtonDown est un RoutedEvent qui, lorsqu’il est déclenché, est transmis de contrôle enfant à contrôle parent (ainsi de suite jusqu’au contrôle racine). Or, s’il arrive en haut de l’arbre visuel, il affiche par défaut le menu contextuel “Silverlight”.

1°)Une solution simple est d’indiquer que l’évènement a été géré (e.Handled = true) dans la callback de l’événement.

<UserControl x:Class="RightClickHandled.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <Rectangle Fill="Red" Width="300" Height="200" MouseRightButtonDown="Rectangle_MouseRightButtonDown"></Rectangle>
    </Grid>
</UserControl>
public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void Rectangle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }
    }

Le problème de cette méthode est qu’il faut le mettre sur chacune des callbacks de MouseRightButtonDown. De plus, cela arrête la remontée de l’évenement MouseRightClickDown aux contrôles parent qui doivent peut être y réagir.

2°) Utilisation d’un behavior : Etant donné mon dernier post, je ne pouvais m’empêcher de voir si un behavior peut régler la solution…. et c’est le cas. Pour ceux qui ne connaissent pas les behaviors, vous pouvez vous référez à cette introduction sur les behaviors).

    public class EraseSilverlightContextMenuBehavior : Behavior<UIElement>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.MouseRightButtonDown += new MouseButtonEventHandler(AssociatedObject_MouseRightButtonDown);
        }

        void AssociatedObject_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.MouseRightButtonDown -= new MouseButtonEventHandler(AssociatedObject_MouseRightButtonDown);
        }
    }

Après on associé le behavior au contrôle et le tour est joué.

<UserControl x:Class="RightClickHandled.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:local="clr-namespace:RightClickHandled"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <Rectangle Fill="Red" Width="300" Height="200">
            <i:Interaction.Behaviors>
                <local:EraseSilverlightContextMenuBehavior />
            </i:Interaction.Behaviors>
        </Rectangle>
    </Grid>
</UserControl>

Le soucis avec cette méthode est qu’il faut appliquer le behavior à tous les contrôles ce qui peut devenir lourd.

3°)La solution la plus générique serait de s’abonner à l’événement MouseRightButtonDown du RootVisual contenu dans le App.xaml.cs afin de bloquer l’événement juste afin sa sortie de l’arbre visuel.

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MainPage();
    this.RootVisual.MouseRightButtonDown += (sender2, args) => { args.Handled = true; };
}

Ainsi tous les contrôles de l’arbre visuel peuvent avoir accès à l’évènement sans contrainte. Plus besoin de l’implémenter sur chacun des contrôles car cela est géré au niveau de la racine de l’arbre.

Si vous avez des méthodes plus smart pour faire cela, n’hésitez pas à me les indiquer🙂.

Un commentaire »

  1. […] Supprimer le context menu "Silverlight" […]

    Ping par [Silverlight] Sortie de Silverlight 4 RTW « Astuces DotNet (Sébastien Courtois) — 15/04/2010 @ 23:40


RSS feed for comments on this post. TrackBack URI

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Créez un site Web ou un blog gratuitement sur WordPress.com.

%d blogueurs aiment cette page :