1

我有三个文本块,其文本绑定到三个不同的属性。

<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"); }
}

现在,这些以米为单位,这就是文本块的 StringFormat 属性中的“M”。我想要做的是,当我在单独的文本块上“单击”(通过命令)(这将在使用控制模板的按钮内部)时,我想将上述文本块中的值转换为英尺并添加值后的“F”。再次单击会将其转换回米,依此类推。

我正在考虑添加一个命令,该命令仅基于bool isMeters. 但是,文本块中的值会不断更新(每秒),我不想每次值更改时都调用该函数。有没有我没有想到的更简单的方法来实现这个功能?

笔记:

1 meter = 3.2808 ft
1ft = 0.3048 meter
4

2 回答 2

2

您可以为每个 TextBlock 中的每个属性使用 a <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")如果您不再需要在视图中绑定此原始属性,您现在可以省略。

于 2016-12-02T17:43:56.703 回答
0

我使用转换器让它工作。

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 答案也有效,只是在我这样做之后才看到它。

于 2016-12-05T12:30:09.140 回答