UpdateSourceTrigger = PropertyChanged和Converter

时间:2009-06-12 15:00:36

标签: c# .net wpf xaml converter

我有一个简单的Converter,它在TextBox中输入的正数中添加了一个“+”符号。当输入数字时,我想启动一些操作,但我不想等到TextBox失去焦点:我想在用户输入文本时立即更新绑定。

TextBox的默认行为是当用户离开框时,更新绑定源(UpdateSourceTrigger = LostFocus)。在这种情况下,我的转换器按预期工作,并添加+。但是,当我将其更改为以下内容时,+ 永远不会添加。

<TextBox Text="{Binding Value, Converter={StaticResource PlusConverter}, UpdateSourceTrigger=PropertyChanged}" />

我可以想象有一个很好的理由为什么我的converter.Convert()方法没有被调用。我想有以下行为:

  1. 当用户输入文字时,源会立即更新
  2. TextBox失去焦点时,会添加+。
  3. 现在我正在寻找一种不错的,但特别是GENERIC的方式(因为我在我的应用程序中有很多这些TextBox)。 到目前为止,我还没有找到合适的解决方案。

4 个答案:

答案 0 :(得分:1)

与Kent B达成协议,您需要发布转换器代码。

我已经能够使用简单的转换器获得第1部分(我正在绑定第二个未转换的TextBlock以显示该值确实正在更新)。

但是,如果我理解你的第2部分,你就会在失去焦点后尝试用“+”更新 TextBox 的文本。这有点棘手,我不认为你只能使用IConverter来做到这一点。如果可以做到,我也很想知道答案。

您基本上要求的是水印输入行为,例如允许用户输入一些数据,并使其正确格式化(在基础DataBinding和UI中)。最快/最肮脏的解决方案是处理TextBoxes的LostFocus,但由于你在整个应用程序中使用它,这可能是不可行的。

您还可以考虑将TextBox包装在您自己的UserControl中。如果你看看WPFToolkit的DatePicker实现,它有类似的行为:允许用户输入自由格式文本,然后自动将值转换为DateTime(如果有效)并以本地化格式显示DateTime。

HTH。

答案 1 :(得分:1)

您可能想要做的另一件事是编辑TextBox的模板并将实际的PART_ContentHost向右移动一点,然后让TextBlock指示+/-部分;即从以下位置更改TextBox的模板:

Control
- Border
-- PART_ContentHost (the actual editing part)

成:

Control
- Border
-- Horizontal StackPanel
--- TextBlock (contains +/- sign, has 2px right margin)
--- PART_ContentHost (actual editable section)

然后,将TextBlock的内容绑定到文本,但使用转换器写入“+”或“ - ”。这样,用户无法删除+/-部分,您不必担心解析它;如果你想做一些像做负号的红色或其他东西,这也会让你更容易。

答案 2 :(得分:1)

感谢您的回答!我自己进一步调查了这个问题并提出了以下解决方案(我并不完全满意,但它工作正常)

我创建了一个CustomControl,它为TextBox添加了功能。

它为LostFocus事件提供了一个事件处理程序 发生此事件时,将调用我的转换器。

然而,我解析转换器的方式并不令人满意(我从与TextBox相关联的Style中获取它)。 Style具有Text属性的Setter。从那个setter我可以访问我的转换器。

当然我也可以制作一个“PlusTextBox”,但我使用不同的转换器,我想要一个通用的解决方案。

public class TextBoxEx : TextBox
{
    public TextBoxEx()
    {
        AddHandler(LostFocusEvent,
          new RoutedEventHandler(CallConverter), true);
    }

    public Type SourceType
    {
        get { return (Type)GetValue(SourceTypeProperty); }
        set { SetValue(SourceTypeProperty, value); }
    }

    // Using a DependencyProperty as the backing store for SourceType.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SourceTypeProperty =
        DependencyProperty.Register("SourceType", typeof(Type), typeof(TextBoxEx), new UIPropertyMetadata(null));

    private static void CallConverter(object sender, RoutedEventArgs e)
    {
        TextBoxEx textBoxEx = sender as TextBoxEx;
        if (textBoxEx.Style == null) {
            return;
        }
        if (textBoxEx.SourceType == null) {
        }
        foreach (Setter setter in textBoxEx.Style.Setters) {
            if (setter.Property.ToString() == "Text") {
                if (! (setter.Value is Binding) ) {
                    return;
                }
                Binding binding = setter.Value as Binding;
                if (binding.Converter == null) {
                    return;
                }
                object value = binding.Converter.ConvertBack(textBoxEx.Text, textBoxEx.SourceType, binding.ConverterParameter, System.Globalization.CultureInfo.CurrentCulture);
                value = binding.Converter.Convert(value, typeof(string), binding.ConverterParameter, System.Globalization.CultureInfo.CurrentCulture);
                if (!(value is string)) {
                    return;
                }
                textBoxEx.Text = (string)value;
            }
        }
    }
}

答案 3 :(得分:0)

在你的转换器中,你不能只检查键盘的当前焦点吗?类似的东西:

TextBox focusedTextBox = Keyboard.FocusedElement as TextBox;
if (focusedTextBox == null || focusedTextBox != senderOrWhatever)
{
 ' this is where you'd add the +, because the textbox doesn't have focus.
}