2016-12-02 11 views
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}" /> 

Эти свойства в 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 имущества текстовых блоков. То, что я пытаюсь сделать, - это когда я 'click' (через команду) на отдельном текстовом блоке (это будет внутри кнопки с использованием шаблона управления), я хочу преобразовать значения в приведенных выше текстовых блоках в ногу и добавить «F» после значения. Еще один щелчок преобразует его обратно в метры и т. Д.

Я думал о добавлении команды, которая просто преобразует значения на основе bool isMeters. Тем не менее, значения в текстовом блоке постоянно обновляются (каждую секунду), и я не хочу, чтобы вы вызывали функцию каждый раз, когда значения меняются. Есть ли более простой способ, я не думаю, чтобы достичь этой функциональности?

Примечание:

1 meter = 3.2808 ft 
1ft = 0.3048 meter 

ответ

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

Тогда в 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 ответить также работал, просто не видел этого до тех пор, пока я так не сделал.

1

Вы можете использовать <MultiBinding> с IMultiValueConverter для каждого свойства в каждом TextBlock, но, на мой взгляд, это будет просто испортите весь код 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"), если вам не нужно связывать это сырое свойство в представлении.

 Смежные вопросы

  • Нет связанных вопросов^_^