WPF行为

发布时间 2023-12-06 10:48:32作者: ZHIZRL

在WPF(Windows Presentation Foundation)中,行为被用来封装一些通用的界面功能在WPF(Windows Presentation Foundation)中,行为被用来封装一些通用的界面功能,这样可以提高代码的重用性和开发效率。行为模型虽然不是WPF的核心部分,但它仍然是一个强大的工具,能够简化UI界面XAML代码的复杂性和复用性。

与触发器不同,触发器通常只能用于同一种类型的控件,而一个行为可以在不同类型的控件下使用,只要这些控件指定了相同的父类。在实际应用中,行为常常用于实现页面效果,它可以替代或减少对元素样式(Style)和触发器(Trigger)的依赖,从而减少代码量。

创建行为

创建行为需要安装Behaviors包

创建一个行为类,用来封装事件逻辑:对象移动的事件

    // 创建一个行为类,用来封装事件逻辑:对象移动的事件 
    public class DragMoveBehavior : Behavior<FrameworkElement>
    {
        // 执行当前行为所依附的对象的事件挂载
        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
            AssociatedObject.MouseMove += AssociatedObject_MouseMove;
            AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
            AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
            AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp;
        }

        private void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            is_obj_moving = false;

            Mouse.Capture(null);
        }

        private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
        {
            if (is_obj_moving == false) return;

            //光标移动后,在Canvas上的当前位置


            Point p = e.GetPosition(AssociatedObject.Parent as Canvas);

            double offset_x = p.X - start_point.X;   // 偏移100
            double offset_y = p.Y - start_point.Y;   // 偏移50


            Canvas.SetLeft((UIElement)sender, start_x + offset_x);
            Canvas.SetTop((UIElement)sender, start_y + offset_y);
        }

        private void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // 获取光标在Canvas上的当前位置
            start_point = e.GetPosition(AssociatedObject.Parent as Canvas);

            start_x = Canvas.GetLeft((UIElement)sender);// 当前50
            start_y = Canvas.GetTop((UIElement)sender); // 当前50

            is_obj_moving = true;

            // 把对象绑定到光标上   两种处理
            // 1、
            Mouse.Capture((UIElement)sender);
        }
        private Point start_point;
        private double start_x, start_y;
        private bool is_obj_moving = false;
    }

使用行为

在Xaml中需要引入behaviors包

为Border和Label添加行为DragMoveBehavior

<Window x:Class="Zhaoxi.EventLesson.BehaviorWindow"
        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:Zhaoxi.EventLesson"
        xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="BehaviorWindow" Height="450" Width="800">
    <Canvas>
        <Border Width="200" Height="50" Background="Orange" Canvas.Left="0" Canvas.Top="0">
            <b:Interaction.Behaviors>
                <local:DragMoveBehavior/>
            </b:Interaction.Behaviors>
        </Border>
        <Border Width="200" Height="50" Background="Green" Canvas.Left="200" Canvas.Top="50">
            <b:Interaction.Behaviors>
                <local:DragMoveBehavior/>
            </b:Interaction.Behaviors>
        </Border>
        <Label Content="Label" Width="100" Height="40" Background="Gray" 
               Canvas.Left="100" Canvas.Top="80">
            <b:Interaction.Behaviors>
                <local:DragMoveBehavior/>
            </b:Interaction.Behaviors>
        </Label>

        <!--目前所封装的Behavior最好不要用Button来测试-->
        <!--<Button Width="300" Height="300"/>-->
    </Canvas>
</Window>

运行效果如下,Border和Label控件可以任意拖动