在Silverlight中自身并沒有提供拖放功能的相關實現,要實現拖放功能得借助其事件支持(MouseLeftButtonDown、MouseLeftButtonUp和MouseMove)來完成,實際應用中我們可以通過行為(Behavior)特性將拖放操作封裝為行為,這樣可達到代碼復用的效果。而在Blend中則直接提供了拖放操作行為,它位于Microsoft.Expression.Interactions.dll的Microsoft.Expression.Interactivity.Layout名稱空間下。
?
Silverlight中的拖放操作通常是使用事件驅動動態定位對象的坐標來實現,首先來看看如何通過代碼的可編程方式在Silverlight中實現拖放操作,如下代碼塊:
{
????FrameworkElement?element?=?sender?as?FrameworkElement;
????MousePosition?=?e.GetPosition(null);
????IsMouseCaptured?=?true;
????element.CaptureMouse();
????element.Cursor?=?Cursors.Hand;
}
private?void?OnMouseLeftButtonUp(object?sender,?MouseButtonEventArgs?e)
{
????FrameworkElement?element?=?sender?as?FrameworkElement;
????IsMouseCaptured?=?false;
????element.ReleaseMouseCapture();
????MousePosition.X?=?MousePosition.Y?=?0;
????element.Cursor?=?null;
}
private?void?OnMouseMove(object?sender,?MouseEventArgs?e)
{
????FrameworkElement?element?=?sender?as?FrameworkElement;
????if?(IsMouseCaptured)
????{
????????double?Y?=?e.GetPosition(null).Y?-?MousePosition.Y;
????????double?X?=?e.GetPosition(null).X?-?MousePosition.X;
????????X?=?X?+?(double)element.GetValue(Canvas.LeftProperty);
????????Y?=?Y?+?(double)element.GetValue(Canvas.TopProperty);
????????element.SetValue(Canvas.LeftProperty,?X);
????????element.SetValue(Canvas.TopProperty,?Y);
????????MousePosition?=?e.GetPosition(null);
????}
}
?
如上定義好的三個方法實現了對象的拖放算法,實際應用中只需要將需要進行拖放移動的對象分別添加MouseLeftButtonDown、MouseLeftButtonUp和MouseMove事件處理就行了。如下示例代碼:
attachedElement.MouseLeftButtonUp?+=?(s,?e)?=>?OnMouseLeftButtonUp(s,?e);
attachedElement.MouseMove?+=?(s,?e)?=>?OnMouseMove(s,?e);
?
按照常規做法我們會將以上相關方法的實現封裝為一個基類以達到復用的目的,但本文不推薦使用基類去封裝拖放行為,因為Silverlight有專門用于處理對象行為的特性-Behaviors。在Silverlight中System.Windows.Interactivity命名空間下提供了行為的基礎框架,我們可以進行自由的擴展行為以實現自己的不同需求。安裝Blend后可以在安裝目錄下找到Microsoft.Expression.Interactivity.dll這個庫,這個庫提供了一些比較常用的集中行為擴展,在Blend中通過“窗口”--“資產”打開資產面板,選擇行為資產就可以查看到Silverlight 3中所提供的擴展行為,如下圖:
?
?
我們可以將上面實現對象拖放的功能封裝為行為以達到代碼復用,在Blend中通過“文件”--“新建”菜單項可打開新建對象對話框。
?
Blend新建向導創建的行為提供了一套行為模板,如下代碼塊:
{
????public?Behavior1()
????{
????????//?在此點下面插入創建對象所需的代碼。
????????//
????????//?下面的代碼行用于在命令
????????//?與要調用的函數之間建立關系。如果您選擇
????????//?使用?MyFunction?和?MyCommand?的已注釋掉的版本,而不是創建自己的實現,
????????//?請取消注釋以下行并添加對?Microsoft.Expression.Interactions?的引用。
????????//
????????//?文檔將向您提供簡單命令實現的示例,
????????//?您可以使用該示例,而不是使用?ActionCommand?并引用?Interactions?程序集。
????????//
????????//this.MyCommand?=?new?ActionCommand(this.MyFunction);
????}
????protected?override?void?OnAttached()
????{
????????base.OnAttached();
????????//?插入要在將?Behavior?附加到對象時運行的代碼。
????}
????protected?override?void?OnDetaching()
????{
????????base.OnDetaching();
????????//?插入要在從對象中刪除?Behavior?時運行的代碼。
????}
????/*
????public?ICommand?MyCommand
????{
????????get;
????????private?set;
????}
?????
????private?void?MyFunction()
????{
????????//?插入要在從對象中刪除?Behavior?時運行的代碼。
????}
????*/
}
?
要實現自定義行為通過此行為模板進行自我擴展就行了,位于System.Windows.Interactivity中的Behavior提供了將行為或命令進行封裝以達到可進行附加到其他的一個對象上,需要注意的是自定義行為默認繼承Behavior<DependencyObject>,使用DependencyObject類型的行為是不能訪問對象的鼠標事件的,如果要訪問鼠標操作的事件,可以使用具體的UI組件類型或者直接使用UI元素基類UIElement。
?
下面為將本篇前面實現對象拖放功能的代碼進行了行為的封裝,完整代碼如下:
///?Behavior:封裝行為和命令,便于附加到對象中。
///?DependencyObject:不能實現訪問鼠操作事件
///?UIElement:可訪問鼠標事件
///?</summary>
public?class?DragBehavior?:?Behavior<UIElement>
{
????private?UIElement?attachedElement;
????private?UserControl?parent;
????private?bool?IsMouseCaptured;
????private?Point?MousePosition;
????protected?override?void?OnAttached()
????{
????????attachedElement?=?this.AssociatedObject;
????????parent?=?Application.Current.RootVisual?as?UserControl;
????????attachedElement.MouseLeftButtonDown?+=?(s,?e)?=>?OnMouseLeftButtonDown(s,?e);
????????attachedElement.MouseLeftButtonUp?+=?(s,?e)?=>?OnMouseLeftButtonUp(s,?e);
????????attachedElement.MouseMove?+=?(s,?e)?=>?OnMouseMove(s,?e);
????}
????private?void?OnMouseMove(object?sender,?MouseEventArgs?e)
????{
????????FrameworkElement?element?=?sender?as?FrameworkElement;
????????if?(IsMouseCaptured)
????????{
????????????double?Y?=?e.GetPosition(null).Y?-?MousePosition.Y;
????????????double?X?=?e.GetPosition(null).X?-?MousePosition.X;
????????????X?=?X?+?(double)element.GetValue(Canvas.LeftProperty);
????????????Y?=?Y?+?(double)element.GetValue(Canvas.TopProperty);
????????????element.SetValue(Canvas.LeftProperty,?X);
????????????element.SetValue(Canvas.TopProperty,?Y);
????????????MousePosition?=?e.GetPosition(null);
????????}
????}
????private?void?OnMouseLeftButtonUp(object?sender,?MouseButtonEventArgs?e)
????{
????????FrameworkElement?element?=?sender?as?FrameworkElement;
????????IsMouseCaptured?=?false;
????????element.ReleaseMouseCapture();
????????MousePosition.X?=?MousePosition.Y?=?0;
????????element.Cursor?=?null;
????}
????private?void?OnMouseLeftButtonDown(object?sender,?MouseButtonEventArgs?e)
????{
????????FrameworkElement?element?=?sender?as?FrameworkElement;
????????MousePosition?=?e.GetPosition(null);
????????IsMouseCaptured?=?true;
????????element.CaptureMouse();
????????element.Cursor?=?Cursors.Hand;
????}
????protected?override?void?OnDetaching()
????{
????????base.OnDetaching();
????}
}
?
通過行為特性將對象的拖放功能進行封裝以達到復用的目的,以上就全部實現了這個功能,測試可通過Ctrol+Shift+B編譯項目,然后通過“資產”面板就可以發現以上自定義擴展的拖放行為。
?
使用行為非常簡單,打開Blend的資源面板中,選中需要使用的行為,將其拖放到要使用該行為的對象(Blend中設計的界面對象)上就行了。其實在Blend也提供了拖放行為:MouseDragElementBehavior,直接使用這個行為和本篇所介紹的實現達到的是同樣的效果。以下為分別使用這兩種行為所對應生成的XAML編碼:
?
????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"?
????xmlns:local="clr-namespace:DragBehavior"
????xmlns:il="clr-namespace:Microsoft.Expression.Interactivity.Layout;assembly=Microsoft.Expression.Interactions"
????x:Class="DragBehavior.MainControl"
????Width="800"?Height="600">
????<Canvas?x:Name="LayoutRoot"?Background="White">
????????<Rectangle?Fill="#FFFF0000"?Stroke="#FF000000"?Height="100"?Width="100"?Canvas.Left="100"?Canvas.Top="100">
????????????<i:Interaction.Behaviors>
????????????????<il:MouseDragElementBehavior/>
????????????</i:Interaction.Behaviors>
????????</Rectangle>
????????<Ellipse?Fill="#FF0000FF"?Stroke="#FF000000"?Height="100"?Width="100"?Canvas.Top="219"?Canvas.Left="397">
????????????<i:Interaction.Behaviors>
????????????????<local:DragBehavior/>
????????????</i:Interaction.Behaviors>
????????</Ellipse>
????</Canvas>
</UserControl>
?
?
推薦資源:
Expression Blend實例中文教程(9) - 行為快速入門Behaviors
Silverlight中實現強壯的、可復用的拖放行為?
Silverlight & Blend動畫設計系列文章
MSDN:http://msdn.microsoft.com/zh-cn/library/cc189090(VS.95).aspx
http://www.silverlight.net/learn/quickstarts/animations/
?
版權說明
? 本文屬原創文章,歡迎轉載且注明文章出處,其版權歸作者和博客園共有。??
? 作??????者:Beniao
?文章出處:http://beniao.cnblogs.com/? 或? http://www.cnblogs.com/
?