[C#] [WPF] 在MVVM中實現拖拽功能 - 入門

Akira300000發表於2024-05-15

拖拽功能是使用頻率較高的一種互動, 用傳統方法去寫很簡單, 但是在mvvm規則下, 也沒必要弄得很麻煩
我的入門案例就選擇了使用mvvm重寫tutorialspoint - Interaction裡的調色盤案例, view如下
image

MainWindow.xaml

這裡的重點是控制元件要允許拖拽以及對應的事件
目標控制元件, 填充色繫結, 允許drop, drop方法

<!-- #region target-->
<Rectangle
    AllowDrop="True"
    Drop="TargetRect_Drop"
    Fill="{Binding FillColor}"/>
<!--#endregion-->

來源控制元件, 因為要拖動, 所以用MouseMove

<!--#region source-->
<Rectangle
    Fill="Beige"
    MouseMove="SourceRect_MouseMove" />
<!--#endregion-->

MainWindow.xaml.cs

在這裡, 就是寫事件的主要邏輯
1️⃣ 首先, 設定一個全域性變數

MainWindowViewModel MainVM;

2️⃣然後寫方法

// drop方法
private void TargetRect_Drop(object sender, DragEventArgs e)
{
	// GetDataPresent: 檢查e.Data是否可以轉換為string格式來儲存
	if (e.Data.GetDataPresent(DataFormats.StringFormat))
	{
		// GetData: 將資料轉化為string格式, 注意將DataObject型別強制轉為string
		string color = (string)e.Data.GetData(DataFormats.StringFormat);
		// 賦值
		MainVM.FillColor = color;
		//MainVM.FillColorName = (Color)ColorConverter.ConvertFromString(MainVM.FillColor);
	}
}

然後是MouseMove

// drag方法: 滑鼠左鍵點選並拖動時觸發, 因為要拖動,所以需要一個MouseMove事件
private void SourceRect_MouseMove(object sender, MouseEventArgs e)
{
    // 按下左鍵
    if (e.LeftButton == MouseButtonState.Pressed)
    {
        // 指定sender
        Rectangle source = sender as Rectangle;
        // 拖動方法DargDrop.DoDragDrop
        DragDrop.DoDragDrop(source, source.Fill.ToString(), DragDropEffects.Copy);
    }
}

MainViewModel.cs

簡簡單單宣告一下要用的變數

[ObservableProperty]
private string _fillColor = "AliceBlue";

關於DragDrop.DoDragDrop

應該是拖拽行為中比較重要的方法(看了好多都是用這個)
官方文件: https://learn.microsoft.com/en-us/dotnet/api/system.windows.dragdrop.dodragdrop?view=windowsdesktop-8.0

⭐省流: 意思就是這個方法需要指定來源, 傳輸的資料還有效果, 資料會被自動封裝 (目標引用資料的話可以用e.Data.GetData啥的), 返回的就是傳入的拖拽效果enum值⭐

用處: 啟動一次拖拽行為

// 如果dragSource或data為null, 則報錯
public static System.Windows.DragDropEffects DoDragDrop (
	System.Windows.DependencyObject dragSource, 
	object data, 
	System.Windows.DragDropEffects allowedEffects);

引數:
dragSource ➡️ 指代被拖拽的物件
data ➡️ 包含傳輸資料的data物件
allowedEffects ➡️ 行為中允許的拖拽效果, 來自DragDropEffects之中的某個值

返回: 拖拽行為中最終效果, 同樣來自DragDropEffects

DragDrop.DoDragDrop(
	source, 
	source.Fill.ToString(), 
	DragDropEffects.Copy)

source代表被拖拽的控制元件/物件, 傳輸的是source的Fill屬性, 並且會被自動封裝進DataObject中

DragDropEffects - Enum
(不想寫了了直接放圖)
image

相關文章