WPF中Behaviors

行为的好处

可以把复杂的界面逻辑抽象出去,让xaml的界面设计更简单,更清爽

1.安装包

复制代码
Microsoft.Xaml.Behaviors.Wpf

2.简单实现拖动效果

复制代码
<Border Width="100"
        Height="100"
        Background="Red">
    <i:Interaction.Behaviors>
        <i:MouseDragElementBehavior />
    </i:Interaction.Behaviors>
</Border>

3.简单自定义一个行为

定义一个情况文本框的行为

c# 复制代码
public class ClearTextBoxBehavior : Behavior<Button>
{
    // 定义依赖属性,用于绑定目标 TextBox
    public TextBox TargetTextBox
    {
        get => (TextBox)GetValue(TargetTextBoxProperty);
        set => SetValue(TargetTextBoxProperty, value);
    }

    public static readonly DependencyProperty TargetTextBoxProperty =
        DependencyProperty.Register(
            nameof(TargetTextBox),
            typeof(TextBox),
            typeof(ClearTextBoxBehavior),
            new PropertyMetadata(null));

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Click += OnButtonClick; // 订阅按钮点击事件
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.Click -= OnButtonClick; // 清理事件
    }

    private void OnButtonClick(object sender, RoutedEventArgs e)
    {
        TargetTextBox?.SetCurrentValue(TextBox.TextProperty, string.Empty); // 清空文本框
        TargetTextBox?.Focus(); // 可选:清空后聚焦文本框
    }
}

引入

xaml 复制代码
xmlns:local1="clr-namespace:TestBinding.Behaviors"
xaml 复制代码
<StackPanel>
    <TextBox Height="30"
             Name="txtInput"></TextBox>
    <Button Height="30"
            >
        <i:Interaction.Behaviors>
            <local1:ClearTextBoxBehavior TargetTextBox="{Binding ElementName=txtInput}" />
        </i:Interaction.Behaviors>
    </Button>
</StackPanel>

一个可以按上键增加值下键减少值的TextBox

c# 复制代码
public class NumericUpDownBehavior : Behavior<TextBox>
{
    // 定义依赖属性:最小值、最大值、步长
    public double Min
    {
        get => (double)GetValue(MinProperty);
        set => SetValue(MinProperty, value);
    }

    public static readonly DependencyProperty MinProperty =
        DependencyProperty.Register(
            nameof(Min),
            typeof(double),
            typeof(NumericUpDownBehavior),
            new PropertyMetadata(double.MinValue)); // 默认无下限

    public double Max
    {
        get => (double)GetValue(MaxProperty);
        set => SetValue(MaxProperty, value);
    }

    public static readonly DependencyProperty MaxProperty =
        DependencyProperty.Register(
            nameof(Max),
            typeof(double),
            typeof(NumericUpDownBehavior),
            new PropertyMetadata(double.MaxValue)); // 默认无上限

    public double Step
    {
        get => (double)GetValue(StepProperty);
        set => SetValue(StepProperty, value);
    }

    public static readonly DependencyProperty StepProperty =
        DependencyProperty.Register(
            nameof(Step),
            typeof(double),
            typeof(NumericUpDownBehavior),
            new PropertyMetadata(1.0)); // 默认步长=1

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewKeyDown += OnKeyDown;
        AssociatedObject.LostFocus += OnLostFocus;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewKeyDown -= OnKeyDown;
        AssociatedObject.LostFocus -= OnLostFocus;
    }

    private void OnKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Up || e.Key == Key.Down)
        {
            // 解析当前值(兼容不同文化的小数点)
            var text = AssociatedObject.Text.Replace(",", "."); // 统一小数点格式
            if (!double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var currentValue))
                currentValue = 0;

            // 计算新值并限制范围
            var step = e.Key == Key.Up ? Step : -Step;
            currentValue = Math.Clamp(currentValue + step, Min, Max);

            // 更新文本框
            AssociatedObject.Text = currentValue.ToString(CultureInfo.InvariantCulture);
            AssociatedObject.CaretIndex = AssociatedObject.Text.Length;

            e.Handled = true;
        }
    }

    private void OnLostFocus(object sender, RoutedEventArgs e)
    {
        // 失去焦点时格式化并重新检查范围
        if (double.TryParse(AssociatedObject.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
        {
            var clampedValue = Math.Clamp(value, Min, Max);
            AssociatedObject.Text = clampedValue.ToString(CultureInfo.InvariantCulture);
        }
        else
        {
            AssociatedObject.Text = Min.ToString(CultureInfo.InvariantCulture); // 非法输入时重置为最小值
        }
    }
}

输入时可以定制最大值、最小值、步长

复制代码
<TextBox Height="30"
         Name="txtInput">
    <i:Interaction.Behaviors>
        <local1:NumericUpDownBehavior Max="100" Min="0" Step="3" />
    </i:Interaction.Behaviors>
</TextBox>
相关推荐
samble17 小时前
从零搭建工业控制系统(二十二):线程安全与并发控制
c#·wpf·并发·mvvm·线程安全·工业控制
姜穆澜17 小时前
OneID 从 0 到 1 完整生产案例(三)
大数据·wpf
dalong1021 小时前
WPF:MVVM 示例
大数据·wpf
samble1 天前
从零搭建工业控制系统(二十一):状态管理系统——中心状态对象设计
c#·wpf·mvvm·状态管理·工业控制
mengge.cloud2 天前
存储技术基础小白教程
linux·运维·服务器·wpf·存储
DreamLife☼2 天前
复杂Agent系统架构设计
系统架构·wpf·agent·组件·设计·构架·说明
SamChan902 天前
PDF翻译服务端到端基准测试:4款主流方案的吞吐量、延迟、内存占用对比
服务器·网络·python·ai·pdf·wpf
bugcome_com2 天前
Avalonia 控件模板实战:从 WPF 迁移自定义 Button 样式的完整指南
wpf
七夜zippoe2 天前
DolphinDB 故障排查实战:系统、数据库与集群常见问题诊断
数据库·wpf·集群·常见问题·故障排查·dolphindb
dalong103 天前
WPF:箭头绘制程序
wpf·自定义绘制