2024. 1. 4. 15:39
Programming/WPF
개발환경
OS : Window 10 x64 ver.22H2
DevTool : VS2019 ver.16.11.29
Framework : .NET Framework 4.8
Other : DevExpress 22.2
Canvas에 동적으로 TextBlock을 생성하고, 생성된 TextBlock을 마우스 Drag & Drop으로 위치 변경을 할 수 있는 코드
View.xaml
<ScrollViewer Height="550" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Canvas x:Name="xRulerCanvas" />
<ItemsControl x:Name="xItemsControl_Preview" Width="{Binding Width_ItemsControl, UpdateSourceTrigger=PropertyChanged}"
Height="{Binding Height_ItemsControl, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ItemCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left" VerticalAlignment="Top" Background="White"
BorderThickness="1" BorderBrush="DarkGray" Margin="40,40,10,10">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="xCanvas_Preview" ClipToBounds="True">
<Canvas.Background>
<VisualBrush TileMode="Tile" Viewport="{Binding CanvasGridViewport, UpdateSourceTrigger=PropertyChanged}" ViewportUnits="Absolute"
Viewbox="{Binding CanvasGridViewport, UpdateSourceTrigger=PropertyChanged}" ViewboxUnits="Absolute">
<VisualBrush.Visual>
<Rectangle Height="{Binding CanvasGridLength, UpdateSourceTrigger=PropertyChanged}"
Width="{Binding CanvasGridLength, UpdateSourceTrigger=PropertyChanged}" Stroke="{StaticResource NormalBorderColor}"
StrokeThickness="1" StrokeDashArray="5 3" />
</VisualBrush.Visual>
</VisualBrush>
</Canvas.Background>
<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommand Command="{Binding MouseCommand, UpdateSourceTrigger=PropertyChanged}"
EventName="MouseLeftButtonDown" PassEventArgsToCommand="True"/>
<dxmvvm:EventToCommand Command="{Binding MouseCommand, UpdateSourceTrigger=PropertyChanged}"
EventName="PreviewMouseMove" PassEventArgsToCommand="True"/>
<dxmvvm:EventToCommand Command="{Binding MouseCommand, UpdateSourceTrigger=PropertyChanged}"
EventName="PreviewMouseUp" PassEventArgsToCommand="True"/>
</dxmvvm:Interaction.Behaviors>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Canvas_X}"/>
<Setter Property="Canvas.Top" Value="{Binding Canvas_Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="{Binding TextBorderThick}">
<TextBlock Text="{Binding Text}" FontFamily="{Binding FontName}" FontSize="{Binding FontSize}" Margin="{Binding Margin}"
Width="{Binding BarcodeWidth}" Height="{Binding BarcodeHeight}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<dxmvvm:Interaction.Behaviors>
<models:MouseBehavior MouseX="{Binding MouseX, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
MouseY="{Binding MouseY, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</dxmvvm:Interaction.Behaviors>
</ItemsControl>
</Grid>
</ScrollViewer>
위 코드의 dxmvvm:Interaction.Behaviors 부분은 아래와 같이 변경해서 사용할 수 있음.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown" >
<i:InvokeCommandAction Command="{Binding MouseCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
ViewModel.cs
public class ViewModel : INotifyPropertyChanged
{
public ObservableCollection<CanvasItem> ItemCollection { get; set; }
public double MouseX
{
get => GetValue<double>();
set => SetValue(value);
}
public double MouseY
{
get => GetValue<double>();
set => SetValue(value);
}
public double Width_ItemsControl
{
get => GetValue<double>();
set => SetValue(value);
}
public double Height_ItemsControl
{
get => GetValue<double>();
set => SetValue(value);
}
public double CanvasGridLength
{
get => GetValue<double>();
set => SetValue(value);
}
public Rect CanvasGridViewport
{
get => GetValue<Rect>();
set => SetValue(value);
}
private double originMouseX = -1, originMouseY = -1;
private int mouseSelectedIndex = -1;
private bool isMove = false;
public ICommand<object> MouseCommand => new DelegateCommand<object>(MouseCommandMethod);
public PamProPrintManagementViewModel()
{
InitData();
ItemCollection = new ObservableCollection<CanvasItem>();
}
private void InitData()
{
Width_ItemsControl = MAXIMUM_X_POSITION;
Height_ItemsControl = MAXIMUM_Y_POSITION;
CanvasGridLength = 50;
CanvasGridViewport = new Rect(0, 0, 50, 50);
}
private void MouseCommandMethod(object obj)
{
try
{
if (obj != null)
{
MouseEventArgs param = obj as MouseButtonEventArgs;
if (param == null)
{
param = obj as MouseEventArgs;
}
if (param != null)
{
switch (param.RoutedEvent.Name)
{
case "MouseLeftButtonDown": MouseDownCommand(param); break;
case "PreviewMouseMove": MouseMoveCommand(param); break;
case "PreviewMouseUp": MouseUpCommand(); break;
default: break;
}
}
}
}
catch (Exception e)
{
Log.Error(e.Message);
}
}
private void MouseDownCommand(MouseEventArgs param)
{
try
{
int index = SearchSelectedControlIndex(param);
if (index == -1)
{
mouseSelectedIndex = -1;
return;
}
if (index != -1)
{
mouseSelectedIndex = index;
isMove = true;
}
}
catch (Exception e)
{
Log.Error(e.Message);
}
}
private int SearchSelectedControlIndex(MouseEventArgs param)
{
try
{
if (ItemCollection != null && ItemCollection.Count > 0)
{
TextBlock control = param.Source as TextBlock;
double x, y, width, height;
string key = ((CanvasItem)((FrameworkElement)param.Source).DataContext).Item_key;
if (control != null)
{
for (int i = 0; i < ItemCollection.Count; i++)
{
if (ItemCollection[i].Item_key == key)
{
x = (int)PrintDataCollection[i].Canvas_X;
y = (int)PrintDataCollection[i].Canvas_Y;
width = control.ActualWidth;
height = control.ActualHeight;
if (x <= MouseX && y <= MouseY)
{
if (x + width >= MouseX && y + height >= MouseY)
{
originMouseX = MouseX;
originMouseY = MouseY;
return i;
}
}
}
}
}
}
}
catch (Exception e)
{
Log.Error(e.Message);
}
return -1;
}
private void MouseMoveCommand(MouseEventArgs param)
{
try
{
if (mouseSelectedIndex == -1)
{
return;
}
if (isMove)
{
double t_x = MouseX - originMouseX;
double t_y = MouseY - originMouseY;
originMouseX = MouseX;
originMouseY = MouseY;
ItemCollection[mouseSelectedIndex].Canvas_X += t_x;
ItemCollection[mouseSelectedIndex].Canvas_Y += t_y;
if (ItemCollection[mouseSelectedIndex].Canvas_Y < 0)
{
ItemCollection[mouseSelectedIndex].Canvas_Y = 0;
}
else if (ItemCollection[mouseSelectedIndex].Canvas_Y >= Height_ItemsControl - 20)
{
ItemCollection[mouseSelectedIndex].Canvas_Y = Height_ItemsControl - 20;
}
if (ItemCollection[mouseSelectedIndex].Canvas_X < 0)
{
ItemCollection[mouseSelectedIndex].Canvas_X = 0;
}
else if (ItemCollection[mouseSelectedIndex].Canvas_X >= Width_ItemsControl - 20)
{
ItemCollection[mouseSelectedIndex].Canvas_X = Width_ItemsControl - 20;
}
}
}
catch (Exception e)
{
Log.Error(e.Message);
}
}
private void MouseUpCommand()
{
isMove = false;
originMouseX = 0;
originMouseY = 0;
}
}
CanvasItem.cs
public class CanvasItem
{
public string Item_key
{
get => GetValue<string>();
set => SetValue(value);
}
public double Canvas_X
{
get => GetValue<double>();
set => SetValue(value);
}
public double Canvas_Y
{
get => GetValue<double>();
set => SetValue(value);
}
public string Text
{
get => GetValue<string>();
set => SetValue(value);
}
public string FontName
{
get => GetValue<string>();
set => SetValue(value);
}
public FontWeight Bold
{
get => GetValue<FontWeight>();
set => SetValue(value);
}
public double FontSize
{
get => GetValue<double>();
set => SetValue(value);
}
public Thickness TextBorderThick
{
get => GetValue<Thickness>();
set => SetValue(value);
}
public Thickness Margin
{
get => GetValue<Thickness>();
set => SetValue(value);
}
}
'Programming > WPF' 카테고리의 다른 글
[WPF, C#] ScrollViewer ListBox에 컨트롤 동적 생성 (1) | 2024.01.04 |
---|---|
[WPF, C#] Array.Copy() - byte 복사 (0) | 2023.02.17 |
[WPF] UniformGrid에 동적으로 Button 생성하고 Button 속성값 변경하기 (2) | 2021.11.24 |
[WPF] Window 타이틀바 없애기 (0) | 2020.12.15 |
[WPF] MediaElement 동영상 무한재생 (0) | 2020.12.14 |