代码之家  ›  专栏  ›  技术社区  ›  pfinferno

根据命令转换文本框中不断更新的单位

  •  1
  • pfinferno  · 技术社区  · 9 年前

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

    <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}" />
    

    以下是viewmodel中的属性:

    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
    
    2 回复  |  直到 9 年前
        1
  •  2
  •   haindl    9 年前

    你可以用 <MultiBinding> 带着 IMultiValueConverter

    但一个更可行的方法可能是使用双精度和字符串属性对。前者是原始值,通常以米为单位。后者将表示应在视图中显示的当前单位。

    因此,您的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") 如果您不再需要在视图中绑定此原始属性。

        2
  •  0
  •   pfinferno    9 年前

    我用转换器使它工作。

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

    然后在viewmodel中:

    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绑定如下,使用datatrigger:

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

    推荐文章