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>
相关推荐
Java Fans8 小时前
在WPF项目中集成Python:Python.NET深度实战指南
python·.net·wpf
布伦鸽15 小时前
C# WPF 左右布局实现学习笔记(1)
笔记·学习·c#·wpf
code bean2 天前
【WPF】WPF 项目实战:构建一个可增删、排序的光源类型管理界面(含源码)
wpf
沉到海底去吧Go2 天前
【图片识别改名】如何批量将图片按图片上文字重命名?自动批量识别图片文字并命名,基于图片文字内容改名,WPF和京东ocr识别的解决方案
ocr·wpf·图片识别改名·图片识别重命名·图片内容改名
lph19722 天前
自定义事件wpf
wpf
code bean2 天前
【WPF】从普通 ItemsControl 到支持筛选的 ItemsControl:深入掌握 CollectionViewSource 用法
wpf
碎碎念的安静2 天前
WPF可拖拽ListView
c#·wpf
界面开发小八哥3 天前
界面组件DevExpress WPF中文教程:Grid - 如何识别行和卡片?
.net·wpf·界面控件·devexpress·ui开发
TwilightLemon4 天前
WPF 使用CompositionTarget.Rendering实现平滑流畅滚动的ScrollViewer,支持滚轮、触控板、触摸屏和笔
wpf
Vae_Mars6 天前
WPF中自定义消息弹窗
wpf