在我们的WPF项目中,我们使用TextBox让用户输入一些长度度量。此度量可以是毫米,厘米,英寸等(取决于用户配置)。
我们需要在TextBox上显示数字以及当前的测量单位,例如: “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.");
}
}
}
答案 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 };
}
}