简体   繁体   English

wpf TextBox binding stringformat + converter不想一起工作

[英]wpf TextBox binding stringformat + converter don't want to work together

I have custom TextBox that only accepts float as input.我有自定义 TextBox,它只接受 float 作为输入。 I bind it to float property (of custom dependency property) using two-way mode.我使用双向模式将它绑定到浮动属性(自定义依赖属性)。 It uses custom converter to do the string conversion to float and vice versa.它使用自定义转换器将字符串转换为浮点数,反之亦然。 If i don't format the string, obviously it will display such value such as 3,141592653... which has too many digits behind comma, i want to display 2 decimal places but keep the actual data of the precise value .如果我不格式化字符串,显然它会显示这样的值,例如 3,141592653... 逗号后面的数字太多,我想显示 2 位小数但保留精确值的实际数据 however, when i tried to run it, string formatting does not work if i set the converter explicitly, unless i remove the converter property it will work.但是,当我尝试运行它时,如果我明确设置转换器,字符串格式将不起作用,除非我删除转换器属性它将起作用。 So here i can choose either keep the converter or the string formatting.所以在这里我可以选择保留转换器或字符串格式。

I need that converter because wpf default conversion is not enough.我需要那个转换器,因为 wpf 默认转换是不够的。 It convert empty string as 0 and accept both dot and comma as the delimiter of the decimal.它将空字符串转换为 0 并接受点和逗号作为小数点的分隔符。 So how do i make my custom textbox to do both stringformat and converter work?那么如何使我的自定义文本框同时执行字符串格式和转换器工作呢?

Below is the relevant code of my custom TextBox (called DoubleBox)下面是我的自定义TextBox(称为DoubleBox)的相关代码

My custom TextBox XAML (DoubleBox.XAML)我的自定义文本框 XAML (DoubleBox.XAML)

<TextBox ...
         Name="Root">
    <TextBox.Text>
        <Binding ElementName="Root"
                 Path="DoubleValue"
                 Mode="TwoWay"
                 UpdateSourceTrigger="Explicit"
                 Converter="{StaticResource DoubleToString}"
                 StringFormat="{}{0:f2}">
            <Binding.ValidationRules>
                <validationrules:MyDoubleValidationRule>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

My custom TextBox code-behind (DoubleBox.XAML.cs)我的自定义 TextBox 代码隐藏 (DoubleBox.XAML.cs)

public partial class DoubleBox : TextBox
{
    // constructor
    
    public double DoubleValue
    {
        get { return (double)GetValue(DoubleValueProperty); }
        set { SetValue(DoubleValueProperty, value); }
    }

    public static readonly DependencyProperty DoubleValueProperty =
        DependencyProperty.Register(nameof(DoubleValue), typeof(double), typeof(DoubleBox), new PropertyMetadata(0.0));
        
    // method that does the binding update source trigger 
    // (when focus is lost and enter key is pressed)
}

My double to string converter我的双字符串转换器

public class DoubleToString : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((double)value).ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string str = (string)value;
        if (string.IsNullOrEmpty(str))
            return 0;
        str = str.Replace('.', ',');
        if (str.StartsWith(','))
            str = "0" + str;
        return double.Parse(str);
    }
}

Edit for more clarification:编辑以获得更多说明:

I have tried formatting the double value inside the double to string conversion method.我已经尝试在 double 到字符串转换方法中格式化 double 值。 i could round the double first before converting it to string ie return Math.Round(((double)value), 2).ToString();我可以在将其转换为字符串之前先将其舍入,即return Math.Round(((double)value), 2).ToString(); and it display 2 decimal float correctly but remember this is a textbox: the user can modify the value from the textbox itself so it is a TwoWay data binding.它正确显示 2 个十进制浮点数,但请记住这是一个文本框:用户可以修改文本框本身的值,因此它是双向数据绑定。

As soon i give my focus to the TextBox it does not display all the floating point precision, it still display 2 decimal float so when i try to lose the focus, the TextBox convert it back to the source property of double as is, which is the formatted value, which is 2 decimal float, so precision is lost so yes this approach does not work for TwoWay binding.一旦我将焦点放在 TextBox 上,它就不会显示所有浮点精度,它仍然显示 2 个小数浮点数,所以当我试图失去焦点时,TextBox 将它转换回 double 的源属性,即格式化值,它是 2 个十进制浮点数,因此精度丢失所以是的,这种方法不适用于 TwoWay 绑定。

Below is a video link of how it behave in my project if i format the string inside the double to string conversion method: https://media.giphy.com/media/7wWVlzl3orIeVl3G2B/giphy.gif下面是一个视频链接,说明如果我在双字符串转换方法中格式化字符串,它在我的项目中的行为: https://media.giphy.com/media/7wWVlzl3orIeVl3G2B/giphy.gif

i have solved this problem by looking it from other point of view.我已经通过从其他角度看它解决了这个问题。 It exactly does what i want which is display the formatted value (only when focus is lost) and does the conversion它正是我想要的,即显示格式化值(仅当焦点丢失时)并进行转换

Instead of trying to make both stringformat and converter works, i used triggers that is activated when focus is lost.我没有尝试使 stringformat 和转换器都起作用,而是使用了在失去焦点时激活的触发器。 The trigger sets the Text property to the formatted string so the text display the formatted string only when it does not have focus, but when focus is given, it displays the actual value.触发器将 Text 属性设置为格式化字符串,以便文本仅在没有焦点时显示格式化字符串,但在获得焦点时显示实际值。

Below is the updated XAML of the DoubleBox.XAML.下面是 DoubleBox.XAML 的更新 XAML。 Actually it is a UserControl now in my code and put the actual TextBox inside the UserControl, no longer modified TextBox but the method still the same by using trigger that display the formatted string when focus is lost实际上它现在在我的代码中是一个 UserControl 并将实际的 TextBox 放在 UserControl 中,不再修改 TextBox 但方法仍然相同通过使用触发器在失去焦点时显示格式化的字符串

<TextBox.Style>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Text">
            <Setter.Value>
                <Binding ElementName="Root"
                         Path="DoubleValue"
                         Mode="TwoWay"
                         Converter="{StaticResource DoubleToString}"
                         UpdateSourceTrigger="Explicit">
                    <Binding.ValidationRules>
                        <validationRules:DoubleValidationRule/>
                    </Binding.ValidationRules>
                </Binding>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsFocused" Value="False">
                <Setter Property="Text">
                    <Setter.Value>
                        <Binding ElementName="Root"
                                 Path="DoubleValue"
                                 Mode="OneWay"
                                 StringFormat="{}{0:f2}">
                        </Binding>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</TextBox.Style>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM