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>
相关推荐
冰茶_12 小时前
WPF之Frame控件详解
学习·microsoft·微软·c#·wpf·控件
冰茶_1 天前
WPF之ScrollViewer控件详解
学习·microsoft·微软·c#·wpf·控件
CoderIsArt1 天前
三个概念:DataBinding,Dependency Property 与DataTemplate
wpf
Dr.多喝热水2 天前
WPF 导航
wpf·导航·frame·navigationwindw
冰茶_2 天前
WPF之Label控件详解
学习·微软·c#·wpf
baivfhpwxf20232 天前
wpf 输入框 在输入时去除水印
wpf
Dr.多喝热水2 天前
WPF App.xaml 合并资源
wpf·xaml·合并资源
未来影子2 天前
企业级分布式 MCP 方案
分布式·wpf
冰茶_3 天前
WPF之RadioButton控件详解
学习·microsoft·c#·wpf