728x90
반응형
728x170
■ UserControl 클래스을 사용해 사용자 컨트롤에서 드래그 & 드롭을 하는 방법을 보여준다.
▶ 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
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] DataObject 클래스 : GetFormats 메소드를 사용해 자동 변환 없이 사용 가능한 포맷 구하기 (0) | 2022.12.02 |
---|---|
[C#/WPF] DataObject 클래스 : GetDatePresent 메소드를 사용해 자동 변환 없이 특정 포맷 데이터 여부 구하기 (0) | 2022.12.02 |
[C#/WPF] DataObject 클래스 : GetDataPresent 메소드를 사용해 특정 타입 데이터 여부 구하기 (0) | 2022.12.02 |
[C#/WPF] DataObject 클래스 사용하기 (0) | 2022.12.02 |
[C#/WPF] RichTextBox 클래스 : DragOver/Drop 이벤트 사용하기 (0) | 2022.12.02 |
[C#/WPF] DataObject 클래스 : GetDataPresent 메소드를 사용해 특정 포맷 데이터 여부 구하기 (0) | 2022.12.01 |
[C#/WPF] DataObject 클래스 : GetFormats 메소드를 사용해 사용 가능한 포맷 구하기 (0) | 2022.12.01 |
[C#/WPF] DataObject 클래스 : SetData 메소드를 사용해 복수 포맷으로 데이터 설정하기 (0) | 2022.12.01 |
[C#/WPF] DataObject 클래스 사용하기 (0) | 2022.11.30 |
[C#/WPF] UIElement 클래스 : MouseMove/DragEnter/DragLeave/DragOver/Drop 이벤트를 사용해 드래그 & 드롭 사용하기 (0) | 2022.11.30 |
댓글을 달아 주세요