WPF高級教程(十八)行爲

介紹

在講解到樣式的時候我們說,樣式是爲了一系列元素共享一些屬性而存在的,歸根結底是爲了複用代碼和邏輯,而我們學習了觸發器之後,發現我們可以用觸發器寫一些簡單的邏輯到樣式中,但是這種簡單的邏輯有時候遠遠不夠。

當我們要實現一堆元素支持在Cancas上面拖放,停靠,縮放等功能的時候,觸發器就顯得不是那麼夠用了。

我們在複用代碼的時候,有下面三種方法,他們互相補充,構建了WPF的屬性重用架構,在合適的場景下選擇合適的方法可以極大的簡化我們的開發工作

  • 樣式,主要是屬性的設置,用觸發器寫的簡單的控件行爲
  • 自定義控件,爲了滿足某一功能編寫的可以公用的專職控件
  • 行爲,封裝了一些通用的用戶界面功能的行爲,可以是十分複雜的功能的集合,一旦創建成功,可以將這種構建好的行爲用於任意一個其他控件中,十分的強大

依賴

行爲的必須依賴 System.Windows.Interactivity,我們在使用的時候可以從網上下載後,添加打項目中,通過引用該dll,引入對於System.Windows.Interactivity的依賴。這一步也是必須的

編寫行爲

我們通過一個例子,直觀的看一下行爲能夠做什麼,爲什麼它比觸發器更加的強大

我們就編寫之前提到過的,我們要通過寫一個行爲,讓一些原本很普通的控件具備在Canvas上被拖動的能力,行爲的編寫如下

public class DragInCanvasBehavior : Behavior<UIElement>
{
    private Canvas canvas;
    private bool isDragging = false;
    private Point mouseOffset;



    protected override void OnAttached()
    {
        base.OnAttached();
        // 綁定事件處理
        this.AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
        this.AssociatedObject.MouseMove += AssociatedObject_MouseMove;
        this.AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
    }

    private void AssociatedObject_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        if (isDragging)
        {
            // 釋放鼠標捕獲
            AssociatedObject.ReleaseMouseCapture();
            isDragging = false;
        }
    }

    private void AssociatedObject_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if (isDragging)
        {
            // 獲取控件在canvas上的位置
            Point point = e.GetPosition(canvas);
            // 移動鼠標的時候確定元素的新位置
            AssociatedObject.SetValue(Canvas.TopProperty, point.Y - mouseOffset.Y);
            AssociatedObject.SetValue(Canvas.LeftProperty, point.X - mouseOffset.X);
        }
    }

    private void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        // 如果canvas不存在,查找canvas
        if (canvas == null)
        {
            canvas = (Canvas)VisualTreeHelper.GetParent(this.AssociatedObject);
        }
        //開始拖動
        isDragging = true;
        // 獲取鼠標點擊控件開始拖動的起始位置
        mouseOffset = e.GetPosition(AssociatedObject);
        // 使得我們要拖動的元素持續的獲取MouseMove事件
        AssociatedObject.CaptureMouse();
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        // 移除事件處理
        this.AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
        this.AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
        this.AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp;
    }
}

需要注意:

  • 要使用行爲,必須依賴 System.Windows.Interactivity
  • 我們一般都是要複寫 OnAttach 和 OnDetaching 兩個方法,用於在組件關聯以及解除關聯的時候,進行事件的監聽和移除監聽
  • 監聽了我們感興趣的事件之後,就可以在事件的處理方法之中寫上控件的行爲

寫出了行爲之後,我們需要將行爲附加到元素上去,使用下面的方法

<Window x:Class="WpfApp1.MainWindow"
        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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d" Unloaded="Window_Unloaded"
        Title="MainWindow" Height="450" Width="800">
    <Canvas>
        <Rectangle Canvas.Left="10" Canvas.Top="10" Fill="Yellow" Width="40" Height="60"></Rectangle>

        <Ellipse Canvas.Left="10" Canvas.Top="70" Fill="Blue" Width="80" Height="60">
            <i:Interaction.Behaviors>
                <local:DragInCanvasBehavior></local:DragInCanvasBehavior>
            </i:Interaction.Behaviors>
        </Ellipse>
    </Canvas>
</Window>

需要注意的是:

  • xaml中同樣需要引入 Interactivity
  • 只需要簡單的將行爲附加於控件,就實現了行爲中寫入的功能,十分的方便

Blend 支持

我們在編程的時候,如果使用Blend構建頁面,如果寫過一個行爲之後,可以在Blend的資產面板中找到這個行爲,直接拖放,就可以給一個元素添加我們新寫的行爲。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章