编辑模式

时间:2015-08-03 17:31:41

标签: wpf textbox

在我们的WPF项目中,我们使用TextBox让用户输入一些长度度量。此度量可以是毫米,厘米,英寸等(取决于用户配置)。

我们需要在T​​extBox上显示数字以及当前的测量单位,例如: “120毫米” “16厘米” “1'2 3/4” 等等。

我正在使用ValueConverter来执行单位转换并添加额外的格式。 UpdateSourceTrigger是默认值,因此绑定适用于用户离开控件时。

这里的挑战是在编辑值时,不显示这些“mm”或“cm”。所以编辑模式中的前面示例将是: “120” “16” “1 2 3/4”

我怎样才能实现这一目标?

以下是一些cenários的转换器代码:

/// <summary>
/// Converts and formats the value (in milimeters) to the required unit/format
/// </summary>
public class LengthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        LengthUnit unit = MainWindow.CurrentLengthUnit;

        switch (unit.Id)
        {
            case 1: //Milimeters
                return value + " mm";
            case 2: //Centimeters
                return (double)value / 10.0 + " cm";
            default:
                throw new InvalidOperationException("Unknown length unit.");

        }

    }

    public object ConvertBack(object value, Type targetType,
           object parameter, CultureInfo culture)
    {
        string rawValue = value as string;

        LengthUnit unit = MainWindow.CurrentLengthUnit;

        switch (unit.Id)
        {
            case 1: //Milimeters
                return rawValue.Replace("mm", "").Trim();
            case 2: //Centimeters
                return Double.Parse(rawValue.Replace("cm", "").Trim()) * 10.0;
            default:
                throw new InvalidOperationException("Unknown length unit.");
        }
    }
}

2 个答案:

答案 0 :(得分:3)

这是怎么回事: 视图:

<TextBox>
        <TextBox.Style>
            <Style TargetType="TextBox">
                <Style.Triggers>
                        <Trigger Property="IsFocused" Value="False">
                            <Setter Property="Text">
                                <Setter.Value>
                                    <MultiBinding Converter="{StaticResource LengthConverter}">
                                        <Binding Path="Foo"/>
                                        <Binding Path="Text" RelativeSource="{RelativeSource Mode=Self}"/>
                                    </MultiBinding>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter Property="Text" Value="{Binding Foo}"></Setter>
                        </Trigger>
                    </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

转换器:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    if (values.Count() > 1)
    {
      var value = values[1].ToString();
      if (value != String.Empty)
      {
        int output;
        Int32.TryParse(value, out output);
        if (output != (int)values[0])
          return value;
      }
    }
    return String.Format("{0} {1}", values[0], "mm");      
}

答案 1 :(得分:0)

到目前为止,我设法仅使用MultiBinding修复此问题,并将TextBox控件作为参数传递(我认为不是很好)。

在转换器代码上,我检查控件属性“IsFocused”并以我需要的方式返回值。我无法直接在绑定上传递“IsFocused”属性,因为它是只读的,而TextBox是双向绑定到源。

以下代码显示了一些额外的处理程序,用于在控件获得焦点或松散焦点时“强制”绑定。

<TextBox x:Name="leadInTextBox"
                     LostFocus="SizeLostFocus"
                     MouseDoubleClick="SelectText"
                     GotKeyboardFocus="SelectText"
                     PreviewMouseLeftButtonDown="SelectivelyMouseButton"
                     PreviewTextInput="PreviewTextInput">
                    <TextBox.Text>
                        <MultiBinding Mode="TwoWay" Converter="{StaticResource MultiLengthConverter}" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
                            <Binding Source="{x:Static local:ApplicationService.UserInfo}" Path="LeadIn" StringFormat="F2" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
                            <Binding RelativeSource="{RelativeSource Self}" Path="." />
                        </MultiBinding>
                    </TextBox.Text>
                </TextBox>

转换器:

public class MultiLengthConverter : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        LengthUnit currentUnit = ApplicationService.UserInfo.LengthUnit;
        TextBox txtBox = values[1] as TextBox;

        switch (currentUnit)
        {
            case LengthUnit.Millimeter:
                return String.Format("{0:N2}{1}", values[0], txtBox.IsFocused == true ? string.Empty : " mm");
            case LengthUnit.Centimeter:
                return String.Format("{0:N2}{1}", (double)values[0] / 10.0, txtBox.IsFocused == true ? string.Empty : " cm");
            case LengthUnit.DecimalInch:
                return String.Format("{0:N2}{1}", (double)values[0] / 25.4, txtBox.IsFocused == true ? string.Empty : " in");
            default:
                throw new InvalidOperationException("Unknown length unit.");

        }
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
    {
        string rawValue = value as string;

        LengthUnit currentUnit = ApplicationService.UserInfo.LengthUnit;

        object ret;

        switch (currentUnit)
        {
            case LengthUnit.Millimeter:
                ret = Double.Parse(rawValue.Replace("mm", "").Trim());
                break;
            case LengthUnit.Centimeter:
                ret = Double.Parse(rawValue.Replace("cm", "").Trim()) * 10.0;
                break;
            case LengthUnit.DecimalInch:
                ret = Double.Parse(rawValue.Replace("in", "").Trim()) * 25.4;
                break;
            default:
                throw new InvalidOperationException("Unknown length unit.");
        }

        return new object[] { ret, null };
    }
}