【问题标题】:Access complete bound value of a textbox in attached property访问附加属性中文本框的完整绑定值
【发布时间】:2018-05-28 12:16:57
【问题描述】:

使用附加属性,我想在点击 Key.Up 或 Key.Down 时将文本框的值减小/增加该值。

我定义了以下属性:

public static readonly DependencyProperty SmallFloatIncrementProperty = DependencyProperty.RegisterAttached(
      "SmallFloatIncrement",
      typeof(double),
      typeof(InputService),
      new UIPropertyMetadata(0.1));

    public static double GetSmallFloatIncrement(DependencyObject d)
    {
        return (double)d.GetValue(SmallFloatIncrementProperty);
    }

    public static void SetSmallFloatIncrement(DependencyObject d, double value)
    {
        d.SetValue(SmallFloatIncrementProperty, value);
    }

我还在我的 TextBox 上注册了 PreviewKeyDown 并像这样处理它:

    if(e.Key == Key.Up)
    {
      IncrementOrDecrementValue((DependencyObject)sender, true);
    }
    else if (e.Key == Key.Down)
    {
      IncrementOrDecrementValue((DependencyObject)sender, false);              
    }

...

    private static void IncrementOrDecrementValue(DependencyObject sender, bool doIncrement)
    {
        if (sender is TextBox)
        {
          TextBox tb = (TextBox)sender;
          var increment = GetSmallFloatIncrement((DependencyObject)sender);

          var text = tb.Text;
          double textBoxValue = 0.0;
          if (!string.IsNullOrEmpty(text))
          {
             try{
               textBoxValue = Convert.ToDouble(text, FormatProvider);
             }
             catch (FormatException)   { }
          }

          tb.Text = Convert.ToString((doIncrement) ? textBoxValue + increment : textBoxValue - increment, FormatProvider);
          ValidateResult(sender);        
        }
    }

我在检索文本框的值时遇到了问题。例如,如果绑定属性为 1.234,但绑定中定义了 StringFormat = N1,则调用 tb.Text 提供 1.2 而不是整个值。但是我需要将原始值增加指定的数量(该值必须是增量的倍数)。有没有办法检索文本框的完整绑定值?

感谢您的帮助!

【问题讨论】:

    标签: c# binding textbox attached-properties


    【解决方案1】:

    基本上你不想改变文本框的值,你想通过键来改变视图模型的值。因此,正确的解决方案是将此行为直接绑定到视图模型。 所以,这里是持有值本身的附加属性。

    public static double GetSmallFloatIncrement(DependencyObject obj)
    {
        return (double)obj.GetValue(SmallFloatIncrementProperty);
    }
    
    public static void SetSmallFloatIncrement(DependencyObject obj, double value)
    {
        obj.SetValue(SmallFloatIncrementProperty, value);
    }
    
    public static readonly DependencyProperty SmallFloatIncrementProperty =
        DependencyProperty.RegisterAttached("SmallFloatIncrement", typeof(double), typeof(TextBoxExtensions),
            new PropertyMetadata(0.0));
    

    实现此功能并打开/关闭它的另一个附加属性:

    public static bool GetSmallFloatIncrementOn(DependencyObject obj)
    {
        return (bool)obj.GetValue(SmallFloatIncrementOnProperty);
    }
    
    public static void SetSmallFloatIncrementOn(DependencyObject obj, bool value)
    {
        obj.SetValue(SmallFloatIncrementOnProperty, value);
    }
    
    public static readonly DependencyProperty SmallFloatIncrementOnProperty =
        DependencyProperty.RegisterAttached("SmallFloatIncrementOn", typeof(bool), typeof(TextBoxExtensions),
            new PropertyMetadata(false, OnSmallFloatIncrementOn));
    
    static void OnSmallFloatIncrementOn(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = (TextBox)d;
    
        void OnKeyDown(object sender, KeyEventArgs keyArgs)
        {
            if (keyArgs.Key == Key.Up)
                IncrementOrDecrementValue(textBox, .01);
            else if (keyArgs.Key == Key.Down)
                IncrementOrDecrementValue(textBox, -.01);
        }
    
        if ((bool)e.NewValue)
            textBox.PreviewKeyDown += OnKeyDown;
        else
            textBox.PreviewKeyDown -= OnKeyDown;
    }
    

    增量函数现在变得简单了:

    static void IncrementOrDecrementValue(TextBox textBox, double inc)
    {
        var cur = GetSmallFloatIncrement(textBox);
        SetSmallFloatIncrement(textBox, cur + inc);
    }
    

    现在我们可以使用它了:

    <TextBox Text="{Binding VMValue, StringFormat=F1}" 
                 local:TextBoxExtensions.SmallFloatIncrement="{Binding VMValue, Mode=TwoWay}"
                 local:TextBoxExtensions.SmallFloatIncrementOn="True"/>
    

    注意:使用这些增量和字符串格式值,您必须按 10 次键,直到您看到 TextBox 中的值发生变化。但这是您可以根据自己的口味调整的东西。

    【讨论】:

    • 感谢 armenm,这看起来是个不错的解决方案。但我还有一个问题:我想根据触发器值将“SmallFloatIncrement”设置为一种样式。如何在那里设置绑定到 VMValue?
    • 您可以创建一个附加属性来保存该值。然后你就可以使用绑定了。
    • 是的,我明白了。但是,如果在您的示例 xaml 代码中,您没有直接在 TextBox 中设置 SmallFloatIncrement 绑定,而是使用样式(位于资源中的某处),您希望根据某些触发器设置 SmallFloatIncrementBinding(例如背景为绿色)?您没有直接访问属性 VMValue 的权限,那么还有其他方法可以设置绑定吗?
    猜你喜欢
    • 2013-09-16
    • 1970-01-01
    • 2017-05-11
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 2018-03-12
    • 2017-07-02
    相关资源
    最近更新 更多