첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

■ Behavior<T> 클래스를 사용해 마우스 왼쪽 버튼 클릭시 컨텍스트 메뉴를 표시하는 방법을 보여준다.

TestProject.zip
다운로드

▶ MouseLeftButtonContextMenuSupportBehavior.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace TestProject
{
    /// <summary>
    /// 마우스 왼쪽 버튼 컨텍스트 메뉴 지원 동작
    /// </summary>
    public class MouseLeftButtonContextMenuSupportBehavior : Behavior<UIElement>
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 마우스 왼쪽 버튼 DOWN 허용 여부 첨부 속성 - AllowMouseLeftMouseDownProperty

        /// <summary>
        /// 마우스 왼쪽 버튼 DOWN 허용 여부 속성
        /// </summary>
        public static readonly DependencyProperty AllowMouseLeftMouseDownProperty = DependencyProperty.RegisterAttached
        (
            "AllowMouseLeftMouseDown",
            typeof(bool),
            typeof(MouseLeftButtonContextMenuSupportBehavior),
            new FrameworkPropertyMetadata(false)
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 마우스 왼쪽 버튼 DOWN 허용 여부 구하기 - GetAllowMouseLeftMouseDown(element)

        /// <summary>
        /// 마우스 왼쪽 버튼 DOWN 허용 여부 구하기
        /// </summary>
        /// <param name="element">UI 엘리먼트</param>
        /// <returns>마우스 왼쪽 버튼 DOWN 허용 여부</returns>
        public static bool GetAllowMouseLeftMouseDown(UIElement element)
        {
            return (bool)element.GetValue(AllowMouseLeftMouseDownProperty);
        }

        #endregion
        #region 마우스 왼쪽 버튼 DOWN 허용 여부 설정하기 - SetAllowMouseLeftMouseDown(element, value)

        /// <summary>
        /// 마우스 왼쪽 버튼 DOWN 허용 여부 설정하기
        /// </summary>
        /// <param name="element">UI 엘리먼트</param>
        /// <param name="value">값</param>
        public static void SetAllowMouseLeftMouseDown(UIElement element, bool value)
        {
            element.SetValue(AllowMouseLeftMouseDownProperty, value);
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Protected

        #region 접착시 처리하기 - OnAttached()

        /// <summary>
        /// 접착시 처리하기
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            if(AssociatedObject != null)
            {
                AssociatedObject.AddHandler
                (
                    UIElement.PreviewMouseLeftButtonDownEvent,
                    new RoutedEventHandler(UIElement_PreviewMouseLeftButtonDown)
                );
            }
        }

        #endregion
        #region 탈착시 처리하기 - OnDetaching()

        /// <summary>
        /// 탈착시 처리하기
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            if(AssociatedObject != null)
            {
                AssociatedObject.RemoveHandler
                (
                    UIElement.PreviewMouseLeftButtonDownEvent,
                    new RoutedEventHandler(UIElement_PreviewMouseLeftButtonDown)
                );
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private

        #region  UI 엘리먼트 프리뷰 마우스 왼쪽 버튼 DOWN 처리하기 - UIElement_PreviewMouseLeftButtonDown(sender, e)

        /// <summary>
        /// UI 엘리먼트 프리뷰 마우스 왼쪽 버튼 DOWN 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UIElement_PreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
        {
            UIElement element = e.Source as UIElement;

            if(element != null)
            {
                if(true.Equals(element.GetValue(MouseLeftButtonContextMenuSupportBehavior.AllowMouseLeftMouseDownProperty)))
                {
                    ContextMenu contextMenu = ContextMenuService.GetContextMenu(element);

                    if(contextMenu != null)
                    {
                        MouseButtonEventArgs eventArgs = new MouseButtonEventArgs
                        (
                            Mouse.PrimaryDevice,
                            Environment.TickCount,
                            MouseButton.Right
                        );

                        eventArgs.RoutedEvent = Mouse.MouseUpEvent;
                        eventArgs.Source      = element;

                        InputManager.Current.ProcessInput(eventArgs);

                        e.Handled = true;
                    }
                }
            }
        }

        #endregion
    }
}

 

▶ TestContextMenu.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace TestProject
{
    /// <summary>
    /// 테스트 컨텍스트 메뉴
    /// </summary>
    public class TestContextMenu : ContextMenu
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 메뉴 항목 클릭 이벤트 - MenuItemClickEvent

        /// <summary>
        /// 메뉴 항목 클릭 이벤트
        /// </summary>
        public static readonly RoutedEvent MenuItemClickEvent = EventManager.RegisterRoutedEvent
        (
            "MenuItemClickEvent",
            RoutingStrategy.Bubble,
            typeof(RoutedEventArgs),
            typeof(TestContextMenu)
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - TestContextMenu()

        /// <summary>
        /// 생성자
        /// </summary>
        public TestContextMenu()
        {
            AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(MenuItem_Click));
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 메뉴 항목 클릭시 처리하기 - MenuItem_Click(sender, e)

        /// <summary>
        /// 메뉴 항목 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            Popup popup = Parent as Popup;

            if(popup != null)
            {
                FrameworkElement targetElement = popup.PlacementTarget as FrameworkElement;

                if(targetElement != null)
                {
                    targetElement.RaiseEvent(new RoutedEventArgs(TestContextMenu.MenuItemClickEvent, e.Source));
                }
            }
        }

        #endregion
    }
}

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:TestProject"
    Width="800"
    Height="600"
    Title="Behavior&lt;T&gt; 클래스 : 마우스 왼쪽 버튼 컨텍스트 메뉴 지원 동작 사용하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Window.Resources>
        <local:TestContextMenu x:Key="TestContextMenuKey">
            <MenuItem Header="Dock to Fill" Tag="FILL" />
            <Separator />
            <MenuItem Header="Dock to Side">
                <MenuItem Header="Left"   Tag="LEFT"   />
                <MenuItem Header="Top"    Tag="TOP"    />
                <MenuItem Header="Right"  Tag="RIGHT"  />
                <MenuItem Header="Bottom" Tag="BOTTOM" />
            </MenuItem>
        </local:TestContextMenu>
    </Window.Resources>
    <i:Interaction.Behaviors>
        <local:MouseLeftButtonContextMenuSupportBehavior />
    </i:Interaction.Behaviors>
    <Grid>
        <Button Name="button"
            Width="100"
            Height="30"
            Padding="5"
            ContextMenu="{DynamicResource TestContextMenuKey}"
            local:MouseLeftButtonContextMenuSupportBehavior.AllowMouseLeftMouseDown="True"
            Content="테스트" />
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            this.button.Click += button_Click; // 실행되지 않는다.

            AddHandler(TestContextMenu.MenuItemClickEvent, new RoutedEventHandler(TestContextMenu_MenuItemClick));
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 버튼 클릭시 처리하기 - button_Click(sender, e)

        /// <summary>
        /// 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("버튼을 클릭했습니다.");
        }

        #endregion
        #region 테스트 컨텍스트 메뉴 항목 클릭시 처리하기 - TestContextMenu_MenuItemClick(sender, e)

        /// <summary>
        /// 테스트 컨텍스트 메뉴 항목 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void TestContextMenu_MenuItemClick(object sender, RoutedEventArgs e)
        {
            MenuItem item = e.OriginalSource as MenuItem;

            MessageBox.Show("컨텍스트 메뉴를 클릭했습니다 : " + item.Header);
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요