Silverlight 拖動復制控件

作者: forgetu  來源: 博客園  發布時間: 2010-09-05 13:20  閱讀: 2867 次  推薦: 0   原文鏈接   [收藏]  

  Silverlight 拖動復制控件,就是將控件從一個容器中向另一個容器中拖動時,不是移動控件而把該控件到另一個容器中。這種情形在程序中經常遇到,下面是我做的一個拖動復制控件的示例,僅供有這種需求的朋友們參考。

  新建一個 Silverlight 項目命名為 DragAndCopy ,在新建的項目中添加一個Silverlight 用戶控件(Silverlight user control)命名為 DragObject。項目結構如下圖所示:Silverlight項目結構

  其中 DragObject 就是要拖動的用戶控件,DragObject 的 Xaml 代碼如下:

 
<UserControl x:Class="DragAndCopy.DragObject"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Image x:Name="icon" Width="128" Height="128" Stretch="Fill" />
</UserControl>

  這里只是演示拖動復制效果,只在 DragObject 中顯示一個圖標。DragObject 的后置代碼如下:

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

namespace DragAndCopy
{

public partial class DragObject : UserControl
{

public DragObject()
{
InitializeComponent();


this.Loaded += new RoutedEventHandler(DragObject_Loaded);
}


/// <summary>
/// 唯一標識一個控件
/// </summary>
public string UUID
{

get;
set;
}


/// <summary>
/// 鼠標點擊的位置
/// </summary>
public Point ClickPos
{

get;
set;
}


/// <summary>
/// 圖標地址(相對)
/// </summary>
public string ImageUri
{

get;
set;
}


void DragObject_Loaded(object sender, RoutedEventArgs e)
{

if (!string.IsNullOrEmpty(ImageUri))
{
BitmapImage bitmap
= new BitmapImage(new Uri(ImageUri, UriKind.Relative));
icon.Source
= bitmap;
}
}
}
}
  DragObject 的 UUID 屬性用來唯一標識一個 DragObject 實例,在鼠標點擊 DragObject 時也是通過 UUID 來判斷是進行移動還是復制。ClickPos 屬性是鼠標點擊 DragObject 的位置,ImageUri 屬性是 DragObject 的圖標的相對地址。

  接下來在 MainPage 中添加幾個 DragObject 的實例,并添加一 Canvas 容器。

 
<UserControl x:Class="DragAndCopy.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DragAndCopy"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="160" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" CornerRadius="5,5,5,5" BorderBrush="Green" BorderThickness="1,1,1,1">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="5,10,5,10">
<local:DragObject ImageUri="icons/chrome.png"
Margin="5,5,5,5"
MouseLeftButtonDown="Handle_MouseLeftButtonDown"
MouseLeftButtonUp="Handle_MouseLeftButtonUp" />
<local:DragObject ImageUri="icons/flock.png"
Margin="5,5,5,5"
MouseLeftButtonDown="Handle_MouseLeftButtonDown"
MouseLeftButtonUp="Handle_MouseLeftButtonUp" />
<local:DragObject ImageUri="icons/galeon.png"
Margin="5,5,5,5"
MouseLeftButtonDown="Handle_MouseLeftButtonDown"
MouseLeftButtonUp="Handle_MouseLeftButtonUp" />
<local:DragObject ImageUri="icons/ie7.png"
Margin="5,5,5,5"
MouseLeftButtonDown="Handle_MouseLeftButtonDown"
MouseLeftButtonUp="Handle_MouseLeftButtonUp" />
<local:DragObject ImageUri="icons/konqueror.png"
Margin="5,5,5,5"
MouseLeftButtonDown="Handle_MouseLeftButtonDown"
MouseLeftButtonUp="Handle_MouseLeftButtonUp" />
<local:DragObject ImageUri="icons/mfirefox.png"
Margin="5,5,5,5"
MouseLeftButtonDown="Handle_MouseLeftButtonDown"
MouseLeftButtonUp="Handle_MouseLeftButtonUp" />
</StackPanel>
</Border>

<Canvas x:Name="rootCanvas" Grid.Row="1" Background="White">

</Canvas>
</Grid>
</UserControl>

  接著實現將 DragObject 從 StackPanel 容器中拖動到 Canvas 容器中時,復制一個 DragObject 到 Canvas 容器。拖動復制這個動作是在 StackPanel 中的 DragObject 上按下鼠標左鍵,然后將鼠標指針拖動到 Canvas 中后彈起鼠標左鍵,由此可知 StackPanel 中的 DragObject 需要響應鼠標左鍵的按下事件,Canvas 需要響應鼠標左鍵的彈起事件。

  先定義兩個變:

 
private DragObject curDrag;
private bool isMouseCaptured;

  curDrag 是用來保存要復制的控件的中間變量,isMouseCaptured 用來判斷是否按鼠標左鍵。

  事件處理代碼如下:

 
void Handle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)?
{
DragObject dragObj
= sender as DragObject;
if (dragObj != null) // 鼠標左鍵在 DragObject 上按下
{
if (string.IsNullOrEmpty(dragObj.UUID)) // 在控件欄中的 DragObject 上按下
{
// 復制要拖動的控件
curDrag = new DragObject();
curDrag.UUID
= Guid.NewGuid().ToString("N"); // 使用 Guid 標識復制的每個控件
curDrag.ImageUri = dragObj.ImageUri;
curDrag.ClickPos
= e.GetPosition(dragObj);
}
isMouseCaptured
= true;
}
}

void Handle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DragObject dragObj
= sender as DragObject;
if (sender is Canvas) // 鼠標左鍵在容器上彈起
{
if (isMouseCaptured)
{
isMouseCaptured
= false;
if (!rootCanvas.Children.Contains(curDrag)) // 復制控件
{
double x = e.GetPosition(rootCanvas).X;
double y = e.GetPosition(rootCanvas).Y;

rootCanvas.Children.Add(
new DragObject
{
ImageUri
= curDrag.ImageUri,
UUID
= curDrag.UUID,
ClickPos
= curDrag.ClickPos
});


// 添加控件的鼠標左鍵按下、彈起事件、設置控件的位置
DragObject obj = rootCanvas.Children.First(ue => (ue as DragObject).UUID == curDrag.UUID) as DragObject;
//obj.MouseMove += Handle_MouseMove;
obj.MouseLeftButtonDown += Handle_MouseLeftButtonDown;

obj.SetValue(Canvas.TopProperty, y
- obj.ClickPos.Y);
obj.SetValue(Canvas.LeftProperty, x
- obj.ClickPos.X);
}
}
}
}

  有了以上的代碼就可以實現用戶控件的復制了。接下實現 Canvas 容器中的控件的拖動事件,拖動控件的是在控件上按下鼠標左鍵,然后移動鼠標,因此控件需要處理鼠標左鍵按下和鼠標移動事件。處理代碼如下:

 
void Handle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragObject dragObj
= sender as DragObject;
if (dragObj != null) // 鼠標左鍵在 DragObject 上按下
{
dragObj.MouseMove
-= Handle_MouseMove;
dragObj.MouseMove
+= Handle_MouseMove;

mouseVerticalPosition
= e.GetPosition(null).Y;
mouseHorizontalPosition
= e.GetPosition(null).X;
dragObj.CaptureMouse();
isMouseCaptured
= true;
}
}

  鼠標移動事件處理代碼如下:

 
void Handle_MouseMove(object sender, MouseEventArgs e)
{
DragObject item
= sender as DragObject;

if (item != null && isMouseCaptured)
{

double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
double newTop = deltaV + (double)item.GetValue(Canvas.TopProperty);
double newLeft = deltaH + (double)item.GetValue(Canvas.LeftProperty);

// 設置新位置
item.SetValue(Canvas.TopProperty, newTop);
item.SetValue(Canvas.LeftProperty, newLeft);


// 更新全局變量
mouseVerticalPosition = e.GetPosition(null).Y;
mouseHorizontalPosition
= e.GetPosition(null).X;
}
}

  通過以上代碼我們實現的拖動復制及移動控件,但是上面的代碼還有一些小 Bug, 完整的示例代碼請到http://zdd.me/myfiles下載。

0
0
 
標簽:Silverlight
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()