根据命令转换文本框中不断更新的单位
Converting constantly updated units in textboxes on command
我有三个文本块,它们的文本绑定到三个不同的属性。
<TextBlock Style="{StaticResource textBlockStyle2}"
Text="{Binding Path=TWD,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged},
StringFormat={}{0:F1} M}" />
<TextBlock Style="{StaticResource textBlockStyle2}"
Text="{Binding Path=Alt,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged},
StringFormat={}{0:F1} M}" />
<TextBlock Style="{StaticResource textBlockStyle2}"
Text="{Binding Path=Dep,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged},
StringFormat={}{0:F1} M}" />
这些是视图模型中的属性:
private double _TWD;
public double TWD
{
get { return _TWD; }
set { _TWD = value; OnPropertyChanged("TWD"); }
}
private double _Alt;
public double Alt
{
get { return _Alt; }
set { _Alt = value; OnPropertyChanged("Alt"); }
}
private double _Dep;
public double Dep
{
get { return _Dep; }
set { _Dep = value; OnPropertyChanged("Dep"); }
}
现在,这些以米为单位,这就是 'M' 在文本块的 StringFormat 属性 中的用途。我想做的是,当我 'click' (通过命令)在一个单独的文本块上(这将在使用控件模板的按钮内)时,我想将上述文本块中的值转换为英尺并在值后添加 'F'。再次单击会将其转换回米,依此类推。
我正在考虑添加一个命令,该命令仅根据 bool isMeters
转换值。但是,文本块中的值会不断更新(每秒),我不想每次值更改时都必须调用该函数。有没有一种我没有想到的更简单的方法来实现这个功能?
注:
1 meter = 3.2808 ft
1ft = 0.3048 meter
您可以对每个 TextBlock 中的每个 属性 使用 <MultiBinding>
和 IMultiValueConverter
,但在我看来,这只会弄乱整个 XAML,所以我真的不推荐它。
但绝对更可行的方法可能是拥有成对的双精度和字符串属性。前者是原始值,可以始终以米为单位。后者代表应显示在视图中的当前单位。
所以您的 ViewModel 看起来像这样:
// This is set by the command.
private bool _isMeters = true;
private double _Alt;
public double Alt
{
get { return _Alt; }
set { _Alt = value; OnPropertyChanged("Alt"); OnPropertyChanged("AltInCurrentUnit"); }
}
// Rename the suffix as you wish.
public string AltInCurrentUnit => GetInCurrentUnit(_Alt);
// This method is used by all "InCurrentUnit"-properties.
private string GetInCurrentUnit(double meters) =>
// If you don't like expression bodied methods or ternaries then reformat as you wish.
_isMeters ?
$"{meters:F1} M" :
$"{(meters * 3.2808):F1} F";
您的视图只需:
<TextBlock Style="{StaticResource textBlockStyle2}" Text="{Binding AltInCurrentUnit}" />
如果您的属性每秒都会刷新一次,那么如果命令更改了单位,那么您可能不需要任何类型的特殊 PropertyChanged
调用。
当然,如果您不再需要在视图中绑定此原始 属性,您现在可以省略 OnPropertyChanged("Alt")
。
我使用转换器让它工作。
public class MetersToFeetConverter : IValueConverter
{
/// <summary>
/// Converts meters to feet.
/// </summary>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
value = (double)value * 3.2808;
return (value.ToString() + " F");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
然后在视图模型中:
private bool _isMeters = true;
public bool IsMeters
{
get { return _isMeters; }
set { _isMeters = value; OnPropertyChanged("IsMeters"); }
}
//called when I click the button to convert
public void ConvertData(object parameter)
{
if (_isMeters == false)
{
IsMeters = true;
}
else
{
IsMeters = false;
}
}
然后 xaml 文本框的绑定是这样的,使用数据触发器:
<Style.Triggers>
<DataTrigger Binding="{Binding IsMeters, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Text" Value="{Binding Path=TWD, Converter={StaticResource metersToFeetConverter}}" />
</DataTrigger>
</Style.Triggers>
注意:@haindl 的回答也有效,只是我这样做后才看到它。
我有三个文本块,它们的文本绑定到三个不同的属性。
<TextBlock Style="{StaticResource textBlockStyle2}"
Text="{Binding Path=TWD,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged},
StringFormat={}{0:F1} M}" />
<TextBlock Style="{StaticResource textBlockStyle2}"
Text="{Binding Path=Alt,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged},
StringFormat={}{0:F1} M}" />
<TextBlock Style="{StaticResource textBlockStyle2}"
Text="{Binding Path=Dep,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged},
StringFormat={}{0:F1} M}" />
这些是视图模型中的属性:
private double _TWD;
public double TWD
{
get { return _TWD; }
set { _TWD = value; OnPropertyChanged("TWD"); }
}
private double _Alt;
public double Alt
{
get { return _Alt; }
set { _Alt = value; OnPropertyChanged("Alt"); }
}
private double _Dep;
public double Dep
{
get { return _Dep; }
set { _Dep = value; OnPropertyChanged("Dep"); }
}
现在,这些以米为单位,这就是 'M' 在文本块的 StringFormat 属性 中的用途。我想做的是,当我 'click' (通过命令)在一个单独的文本块上(这将在使用控件模板的按钮内)时,我想将上述文本块中的值转换为英尺并在值后添加 'F'。再次单击会将其转换回米,依此类推。
我正在考虑添加一个命令,该命令仅根据 bool isMeters
转换值。但是,文本块中的值会不断更新(每秒),我不想每次值更改时都必须调用该函数。有没有一种我没有想到的更简单的方法来实现这个功能?
注:
1 meter = 3.2808 ft
1ft = 0.3048 meter
您可以对每个 TextBlock 中的每个 属性 使用 <MultiBinding>
和 IMultiValueConverter
,但在我看来,这只会弄乱整个 XAML,所以我真的不推荐它。
但绝对更可行的方法可能是拥有成对的双精度和字符串属性。前者是原始值,可以始终以米为单位。后者代表应显示在视图中的当前单位。
所以您的 ViewModel 看起来像这样:
// This is set by the command.
private bool _isMeters = true;
private double _Alt;
public double Alt
{
get { return _Alt; }
set { _Alt = value; OnPropertyChanged("Alt"); OnPropertyChanged("AltInCurrentUnit"); }
}
// Rename the suffix as you wish.
public string AltInCurrentUnit => GetInCurrentUnit(_Alt);
// This method is used by all "InCurrentUnit"-properties.
private string GetInCurrentUnit(double meters) =>
// If you don't like expression bodied methods or ternaries then reformat as you wish.
_isMeters ?
$"{meters:F1} M" :
$"{(meters * 3.2808):F1} F";
您的视图只需:
<TextBlock Style="{StaticResource textBlockStyle2}" Text="{Binding AltInCurrentUnit}" />
如果您的属性每秒都会刷新一次,那么如果命令更改了单位,那么您可能不需要任何类型的特殊 PropertyChanged
调用。
当然,如果您不再需要在视图中绑定此原始 属性,您现在可以省略 OnPropertyChanged("Alt")
。
我使用转换器让它工作。
public class MetersToFeetConverter : IValueConverter
{
/// <summary>
/// Converts meters to feet.
/// </summary>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
value = (double)value * 3.2808;
return (value.ToString() + " F");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
然后在视图模型中:
private bool _isMeters = true;
public bool IsMeters
{
get { return _isMeters; }
set { _isMeters = value; OnPropertyChanged("IsMeters"); }
}
//called when I click the button to convert
public void ConvertData(object parameter)
{
if (_isMeters == false)
{
IsMeters = true;
}
else
{
IsMeters = false;
}
}
然后 xaml 文本框的绑定是这样的,使用数据触发器:
<Style.Triggers>
<DataTrigger Binding="{Binding IsMeters, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Text" Value="{Binding Path=TWD, Converter={StaticResource metersToFeetConverter}}" />
</DataTrigger>
</Style.Triggers>
注意:@haindl 的回答也有效,只是我这样做后才看到它。