日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Silverlight中實現(xiàn)強壯的、可復用的拖放行為

【獨家特稿】簡單的Silverlight拖放行為可以通過某些Silverlight控制實現(xiàn),但Silverlight的總 體表現(xiàn)卻沒有WPF中對行為控制得那么好,不過可以使用附加的行為操作元素的RenderTransform,這樣可以 大大增加Silverlight中拖放實現(xiàn)的強壯性和可復用性。

創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),黃陂企業(yè)網(wǎng)站建設(shè),黃陂品牌網(wǎng)站建設(shè),網(wǎng)站定制,黃陂網(wǎng)站建設(shè)報價,網(wǎng)絡營銷,網(wǎng)絡優(yōu)化,黃陂網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

新型實現(xiàn)

默認情況下Silverlight通過System.Windows.Controls.Primitives中的Thumb控制讓拖放支持變得更容易 ,實現(xiàn)拖放最簡單的方法是使用Thumb控制和為應用程序外觀應用合適的ControlTemplate(控制模板)。但 在某些情況下,使用Thumb不太實際,在XAML中要“模板”化一個Thumb控制是很笨重的,你必須在你使用的 每個單獨的區(qū)域中為應用程序邏輯重復一次這個行為,隨著應用程序的增長,這種需求將會使應用程序的維 護變得異常困難。

不過有兩個新方法讓你可以在任何UI元素上開啟拖放操作,下面是***個方法:

     
      

MouseMove="DragDelta" MouseLeftButtonDown="DragStart" MouseLeftButtonUp="DragComplete"

VerticalAlignment="Top" Fill="#FFC20707" Stroke="#FF000000"/>

這個實現(xiàn)最重要的就是具體開啟拖放操作的事件:MouseMove、MouseLeftButtonDown和 MouseLeftButtonUp,通過在這些事件上增加處理程序,你就可以執(zhí)行一些簡單的拖放操作了。

第二個方法是:

private bool isDragging = false;

private void DragStart(object sender, MouseButtonEventArgs args)

{

   Shape draggable = sender as Shape;

   if (draggable != null)

   {

      isDragging = true;

      draggable.CaptureMouse();

   }

}

private void DragDelta(object sender, MouseEventArgs args)

{

   Shape draggable = sender as Shape;

   if (draggable != null && isDragging)

   {

      Point currentPosition = args.GetPosition(null);

      TranslateTransform transform = draggable.RenderTransform

         as TranslateTransform;

      if (transform == null)

      {

         transform = new TranslateTransform();

         draggable.RenderTransform = transform;

      }

 

      transform.X = (currentPosition.X - draggable.Width / 2);

      transform.Y = (currentPosition.Y - draggable.Height / 2);

   }

}

 

private void DragComplete(object sender, MouseButtonEventArgs args)

{

   Shape draggable = sender as Shape;

   if (draggable != null)

   {

      isDragging = false;

      draggable.ReleaseMouseCapture();

   }

}

正如你所看到的,通過影響控制RenderTransform而不是特定面板布局參數(shù),如Canvas.Top和Canvas.Left 等附加屬性,或是Grid邊緣空白,你可以將一個元素移動到任何一個容器中,而且這種方法對任何一個UI元 素都是可復用的,它不允許你橫跨不同的控制重新使用應用程序邏輯,為此,你需要一個具有附加行為的實 現(xiàn)。

使用附加行為

WPF和.NET 3.0引入了依賴屬性概念,也就是說當屬性發(fā)生變化后,它會通知所有者(它必須是一個 DependencyObject[依賴對象]),允許所有者執(zhí)行一塊應用程序邏輯。

有兩種類型的依賴屬性,最常用的是依賴屬性自身,建立和使用DependencyProperty.Register進行設(shè)置 都是相同的依賴對象。第二種類型是附加屬性,使用DependencyProperty.RegisterAttached進行設(shè)置,附加 屬性被設(shè)置為它所有者不同的類型。

看一下下么的附加屬性例子:

public static readonly DependencyProperty HoverProperty = 

   DependencyProperty.RegisterAttached(

   "Hover",

   typeof(Brush),

   typeof(Hover),

   new PropertyMetadata(null, OnHoverChanged));

通過事件處理程序OnHoverChanged,當你在XAML中設(shè)置那個屬性時,你可以提供一些應用程序邏輯:

private static void OnHoverChanged(DependencyObject obj,   

   DependencyPropertyChangedEventArgs args)

{

   Border border = obj as Border;

   if (border != null)

   {

      if(args.OldValue == null && args.NewValue != null)

      {

         border.MouseEnter += SetHoverBackground;

         border.MouseLeave += SetNotHoverBackground;

      }

      else if(args.OldValue != null && args.NewValue == null)

      {

         border.MouseEnter -= SetHoverBackground;

         border.MouseLeave -= SetNotHoverBackground;

      }

   }

}

OnHoverChanged代碼僅僅簡單地增加了事件處理程序,在觸發(fā)MouseEnter事件時修改對象的背景顏色,觸 發(fā)MouseLeave事件時還原到對象的原始顏色,這段簡短的代碼功能叫做附加行為,附加行為是后面章節(jié)講述 的拖放實現(xiàn)的核心概念,下么來看一個附加行為IsEnabled:

public static readonly DependencyProperty IsEnabledProperty
=

   DependencyProperty.RegisterAttached(

   "IsEnabled",

   typeof(bool),

   typeof(SimpleDragDropBehavior),

   new PropertyMetadata(false, OnIsEnabledChanged));

通過注冊O(shè)nIsEnabledChanged作為改變事件處理程序的屬性,你可以訂閱你前面使用的事件處理程序:

private static void OnIsEnabledChanged(DependencyObject obj, 

   DependencyPropertyChangedEventArgs args)

{

   UIElement dragSource = obj as UIElement;

 

   bool wasEnabled = (args.OldValue != null) ? (bool)args.OldValue : false;

   bool isEnabled = (args.NewValue != null) ? (bool)args.NewValue : false;

//如果行為被禁用,移除這個事件處理程序

   if (wasEnabled && !isEnabled)

   {

      dragSource.MouseLeftButtonDown -= DragStart;

   }

//如果行為被附加,添加這個事件處理程序

   if (!wasEnabled && isEnabled)

   {

      dragSource.MouseLeftButtonDown += DragStart;

   }

}

改變事件處理程序的屬性IsEnabled使用前面談到的新型實現(xiàn)向事件添加處理程序,因此,只需要在你的 應用程序中任何或是有UI元素上重復使用這個行為,但這種新型實現(xiàn)有其自身的設(shè)置限制,還不能立即顯現(xiàn) 出來。

調(diào)用args.GetPosition(null)跟蹤絕對位置不能適應一個允許嵌套拖放的行為,更好的解決辦法是反復計 算拖動的變量,為了解決這個限制,你可以轉(zhuǎn)向私有附加屬性,在思考私有附加行為的范圍時,私有附加屬 性和私有成員變量或?qū)傩灶愃疲哺郊有袨楹凸哺郊訉傩灶愃?。因為你只需要跟蹤你所選元素的x和y坐 標值,因此需要兩個私有附加屬性:

public static readonly DependencyProperty XProperty = 

   DependencyProperty.RegisterAttached(

   "X",

   typeof(double),

   typeof(DragDropBehavior),

   new PropertyMetadata(double.NaN));

 

public static readonly DependencyProperty YProperty =

   DependencyProperty.RegisterAttached(

   "Y",

   typeof(double),

   typeof(DragDropBehavior),

   new PropertyMetadata(double.NaN));

這些屬性的默認值都是double.NAN,表明對象當前沒有拖放位置,這對于后面拖放元素時重置元素是很重 要的,此外這些私有附加屬性,你還需要知道哪些容器是用于參照的,也就是說你需要指定原始的坐標值, (X,Y) = (0,0),你只需要簡單地位你的宿主指定另一個附加屬性:

public static readonly DependencyProperty IsHostProperty 

= 

   DependencyProperty.RegisterAttached(

   "IsHost",

   typeof(bool),

   typeof(DragDropBehavior),

   new PropertyMetadata (false));

現(xiàn)在你已經(jīng)為你反復跟蹤拖放行為建立起了必要的數(shù)據(jù),你需要做的全部內(nèi)容是實現(xiàn)前面定義的相同的三 個處理程序:DragStart,DragDelta,DragComplete。在DragStart中,你可以增加更多的功能,在你的行為 類中改成使用靜態(tài)函數(shù):

private static void DragStart(object sender, MouseButtonEventArgs args)

{

   UIElement dragSource = sender as UIElement;

//創(chuàng)建執(zhí)行拖動操作的TranslateTransform

   TranslateTransform dragTransform = new TranslateTransform();

   dragTransform.X = 0;

   dragTransform.Y = 0;

//如果是首次使用拖放,先要設(shè)置TranslateTransform

   dragSource.RenderTransform = (

      dragSource.RenderTransform is TranslateTransform) ?

      dragSource.RenderTransform : dragTransform;

//分別為MouseMove和MouseLeftButtonUp添加事件處理程序

   dragSource.MouseMove += OnDragDelta;

   dragSource.MouseLeftButtonUp += OnDragComplete;

//捕獲鼠標

   dragSource.CaptureMouse();

}

這和你最初的實現(xiàn)相差不多,你獲得了一個拖動項目,設(shè)置它的RenderTransform,附加適當?shù)氖录幚?程序,并捕獲鼠標。但DragDelta實現(xiàn)完全不同,因為你現(xiàn)在跟蹤的是鼠標動作了,你需要:

1、找到你的宿主容器;

2、相對這個容器計算當前位置;

3、比較前一次記錄的位置和現(xiàn)在的位置,計算出拖動變量;

4、更新RenderTransform和你的私有附加屬性,x和y。

private static void DragDelta(object sender, MouseEventArgs args)

{

   FrameworkElement dragSource = sender as FrameworkElement;

//計算dragSource的偏移量,更新TranslateTransform

   FrameworkElement dragDropHost = FindDragDropHost(dragSource);

   Point relativeLocationInHost = args.GetPosition(dragDropHost);

   Point relativeLocationInSource = args.GetPosition(dragSource);

//獲得當前位置

   double xPosition = GetX(dragSource);

   double yPosition = GetY(dragSource);

//從前一次位置計算變數(shù)

   double xChange = relativeLocationInHost.X - xPosition;

   double yChange = relativeLocationInHost.Y - yPosition;

//如果這不是首次鼠標移動,更新位置

   if (!double.IsNaN(xPosition))

   {

      ((TranslateTransform)dragSource.RenderTransform).X += xChange;

   }

 

   if (!double.IsNaN(yPosition))

   {

      ((TranslateTransform)dragSource.RenderTransform).Y += yChange;

   }

//更新你的私有附加屬性跟蹤拖動位置

   SetX(dragSource, relativeLocationInHost.X);

   SetY(dragSource, relativeLocationInHost.Y);

}

需要特別指出的是找出參照宿主非常重要,不過說來也很簡單,只需要在可視化樹結(jié)構(gòu)中搜索IsHost = true即可。

DragComplete新的實現(xiàn)

現(xiàn)在,DragStart和DragDelta中的部件算是全部弄好了,現(xiàn)在只剩下DragComplete了,和DragStart一樣 ,DragComplete實現(xiàn)和你的新型實現(xiàn)不是完全一樣,值得注意的是它移除了事件處理程序,并釋放了鼠標捕 獲,你也必須重置你的私有附加屬性x和y,指出拖動項目不再進行拖動了。

private static void DragComplete(object sender, 

   MouseButtonEventArgs args)

{

   UIElement dragSource = sender as UIElement;

   dragSource.MouseMove -= DragDelta;

   dragSource.MouseLeftButtonUp -= DragComplete;

//設(shè)置x和y的值,以便下一次MouseDown時好重置

   SetX(dragSource, double.NaN);

   SetY(dragSource, double.NaN);

//釋放鼠標捕獲

   dragSource.ReleaseMouseCapture();

}

這個新的迭代實現(xiàn)克服了前面描述的限制,它也允許流暢跟蹤鼠標,在新的實現(xiàn)中,你只需要把鼠標放在 拖動項目的中心,在前面的實現(xiàn)中,鼠標需要保持放在容器里面。

public static FrameworkElement FindDragDropHost(

   UIElement element)

{

   DependencyObject parent = VisualTreeHelper.GetParent(element);

   while (parent != null && !GetIsHost(parent))

   {

      parent = VisualTreeHelper.GetParent(parent);

   }

   return parent as FrameworkElement;

}

限制和擴展

值得注意的是本文講述的拖放行為也有一些限制,這將成為未來的改進方向。首先,即使這種方法能夠在 一個容器中實現(xiàn)簡單的拖放,但在拖放的不同階段不能接受更強壯的應用程序邏輯,但在WPF中卻可以實現(xiàn), 如DragEnter、DragLeave和Drop在Silverlight中就還不能實現(xiàn),但你可以通過自定義附加事件實現(xiàn)來增加這 些功能。

在設(shè)置IsEnabled后,行為也不能執(zhí)行自定義拖放邏輯,如果在拖放實現(xiàn)中使用了Canvas.Top和 Canvas.Left,意味著你需要使用獨立的附加行為,而不是使用自定義事件。這是因為Silverlight缺乏附加 事件引起的,在Silverlight 3.0這將可能會有這些特性,但你可以通過復雜的行為實現(xiàn)來克服這些限制,這 個內(nèi)容已經(jīng)超出了本文的范疇,這里概述的方法傾向為一個起點,更好的實現(xiàn)希望通過開源Silverlight庫 Quasar來實現(xiàn)。

您正在閱讀的是獨家特稿《Silverlight中實現(xiàn)強壯的、可復用的拖放行為》


當前題目:Silverlight中實現(xiàn)強壯的、可復用的拖放行為
路徑分享:http://www.5511xx.com/article/djdgesh.html