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

■ UserControl 클래스을 사용해 사용자 컨트롤에서 드래그 & 드롭을 하는 방법을 보여준다.

TestProject.zip
0.01MB

▶ CircleControl.xaml

<UserControl x:Class="TestProject.CircleControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    AllowDrop="True">
    <Grid>
        <Ellipse Name="ellipse"
            Height="100"
            Width="100"
            Fill="Blue" />
    </Grid>
</UserControl>

 

▶ CircleControl.xaml.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace TestProject
{
    /// <summary>
    /// 원 컨트롤
    /// </summary>
    public partial class CircleControl : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 이전 채우기 브러시
        /// </summary>
        private Brush previousFillBrush = null;

        #endregion

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

        #region 생성자 - CircleControl()

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

        #endregion
        #region 생성자 - CircleControl(source)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="source">소스 원 컨트롤</param>
        public CircleControl(CircleControl source)
        {
            InitializeComponent();

            HorizontalAlignment = source.HorizontalAlignment;
            Margin              = source.Margin;

            this.ellipse.Width  = source.ellipse.Height;
            this.ellipse.Height = source.ellipse.Height;
            this.ellipse.Fill   = source.ellipse.Fill;
        }

        #endregion

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

        #region 마우스 이동시 처리하기 - OnMouseMove(e)

        /// <summary>
        /// 마우스 이동시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if(e.LeftButton == MouseButtonState.Pressed)
            {
                DataObject dataObject = new DataObject();

                dataObject.SetData(DataFormats.StringFormat, ellipse.Fill.ToString());
                dataObject.SetData("Double"                , ellipse.Height         );
                dataObject.SetData("Object"                , this                   );

                DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Copy | DragDropEffects.Move);
            }
        }

        #endregion
        #region 피드백 제공시 처리하기 - OnGiveFeedback(e)

        /// <summary>
        /// 피드백 제공시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
        {
            base.OnGiveFeedback(e);

            if(e.Effects.HasFlag(DragDropEffects.Copy))
            {
                Mouse.SetCursor(Cursors.Cross);
            }
            else if(e.Effects.HasFlag(DragDropEffects.Move))
            {
                Mouse.SetCursor(Cursors.Pen);
            }
            else
            {
                Mouse.SetCursor(Cursors.No);
            }

            e.Handled = true;
        }

        #endregion

        #region 드래그 진입시 처리하기 - OnDragEnter(e)

        /// <summary>
        /// 드래그 진입시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnDragEnter(DragEventArgs e)
        {
            base.OnDragEnter(e);

            this.previousFillBrush = this.ellipse.Fill;

            if(e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                string fillBrushString = e.Data.GetData(DataFormats.StringFormat) as string;

                BrushConverter converter = new BrushConverter();

                if(converter.IsValid(fillBrushString))
                {
                    Brush fillBrush = converter.ConvertFromString(fillBrushString.ToString()) as Brush;

                    this.ellipse.Fill = fillBrush;
                }
            }
        }

        #endregion
        #region 드래그 OVER 처리하기 - OnDragOver(e)

        /// <summary>
        /// 드래그 OVER 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnDragOver(DragEventArgs e)
        {
            base.OnDragOver(e);

            e.Effects = DragDropEffects.None;

            if(e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                string fillBrushString = e.Data.GetData(DataFormats.StringFormat) as string;

                BrushConverter converter = new BrushConverter();

                if(converter.IsValid(fillBrushString))
                {
                    if(e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                    {
                        e.Effects = DragDropEffects.Copy;
                    }
                    else
                    {
                        e.Effects = DragDropEffects.Move;
                    }
                }
                else
                {
                    e.Effects = DragDropEffects.None;
                }
            }

            e.Handled = true;
        }

        #endregion
        #region 드래그 이탈시 처리하기 - OnDragLeave(e)

        /// <summary>
        /// 드래그 이탈시 처리하기
        /// </summary>
        /// <param name="e">이벤트 발생자</param>
        protected override void OnDragLeave(DragEventArgs e)
        {
            base.OnDragLeave(e);

            this.ellipse.Fill = this.previousFillBrush;
        }

        #endregion
        #region 드롭시 처리하기 - OnDrop(e)

        /// <summary>
        /// 드롭시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnDrop(DragEventArgs e)
        {
            base.OnDrop(e);

            if(e.Data.GetDataPresent(DataFormats.StringFormat))
            {
                string fillBrushString = e.Data.GetData(DataFormats.StringFormat) as string;

                BrushConverter converter = new BrushConverter();

                if(converter.IsValid(fillBrushString))
                {
                    Brush fillBrush = converter.ConvertFromString(fillBrushString) as Brush;

                    this.ellipse.Fill = fillBrush;

                    if(e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                    {
                        e.Effects = DragDropEffects.Copy;
                    }
                    else
                    {
                        e.Effects = DragDropEffects.Move;
                    }
                }
            }

            e.Handled = true;
        }

        #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:local="clr-namespace:TestProject"
    Width="800"
    Height="600"
    Title="TestProject"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*"    />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"  />
            <ColumnDefinition Width="10" />
            <ColumnDefinition Width="*"  />
        </Grid.ColumnDefinitions>
        <TextBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="32"
            Margin="0 10 0 10"
            Height="25"
            VerticalContentAlignment="Center"
            Text="green" />
        <StackPanel Name="stackPanel1" Grid.Row="1" Grid.Column="0"
            Background="Beige"
            AllowDrop="True">
            <local:CircleControl
                HorizontalAlignment="Center"
                Margin="10" />
            <local:CircleControl
                HorizontalAlignment="Center"
                Margin="10" />
        </StackPanel>
        <StackPanel Name="stackPanel2" Grid.Row="1" Grid.Column="2"
            Background="Bisque"
            AllowDrop="True" />
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

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

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

        #region 생성자 - MainWindow()

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

            this.stackPanel1.DragOver += stackPanel_DragOver;
            this.stackPanel1.Drop     += stackPanel_Drop;
            this.stackPanel2.DragOver += stackPanel_DragOver;
            this.stackPanel2.Drop     += stackPanel_Drop;
        }

        #endregion

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

        #region 스택 패널 드래그 OVER 처리하기 - stackPanel_DragOver(sender, e)

        /// <summary>
        /// 스택 패널 드래그 OVER 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void stackPanel_DragOver(object sender, DragEventArgs e)
        {
            if(e.Data.GetDataPresent("Object"))
            {
                if(e.KeyStates == DragDropKeyStates.ControlKey)
                {
                    e.Effects = DragDropEffects.Copy;
                }
                else
                {
                    e.Effects = DragDropEffects.Move;
                }
            }
        }

        #endregion
        #region 스택 패널 드롭시 처리하기 - stackPanel_Drop(sender, e)

        /// <summary>
        /// 스택 패널 드롭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void stackPanel_Drop(object sender, DragEventArgs e)
        {
            if(e.Handled == false)
            {
                Panel targetPanel = sender as Panel;

                UIElement sourceElement = (UIElement)e.Data.GetData("Object");

                if(targetPanel != null && sourceElement != null)
                {
                    Panel sourcePanel = (Panel)VisualTreeHelper.GetParent(sourceElement);

                    if(sourcePanel != null)
                    {
                        if(e.KeyStates == DragDropKeyStates.ControlKey && e.AllowedEffects.HasFlag(DragDropEffects.Copy))
                        {
                            CircleControl circleControl = new CircleControl((CircleControl)sourceElement);

                            targetPanel.Children.Add(circleControl);

                            e.Effects = DragDropEffects.Copy;
                        }
                        else if(e.AllowedEffects.HasFlag(DragDropEffects.Move))
                        {
                            sourcePanel.Children.Remove(sourceElement);

                            targetPanel.Children.Add(sourceElement);

                            e.Effects = DragDropEffects.Move;
                        }
                    }
                }
            }
        }

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

댓글을 달아 주세요