2009-05-08 17 views
39

J'ai une valeur booléenne que j'ai besoin d'afficher comme "Oui" ou "Non" dans un TextBlock. J'essaye de faire ceci avec un StringFormat, mais mon StringFormat est ignoré et le TextBlock affiche "True" ou "False".WPF: Afficher une valeur booléenne comme "Oui"/"Non"

<TextBlock Text="{Binding Path=MyBoolValue, StringFormat='{}{0:Yes;;No}'}" /> 

Y at-il un problème avec ma syntaxe ou ce type de StringFormat n'est-il pas pris en charge?

Je sais que je peux utiliser un ValueConverter pour accomplir cela, mais la solution StringFormat semble plus élégante (si ça a marché).

Répondre

37

Votre solution avec StringFormat ne peut pas fonctionner, car ce n'est pas une chaîne de format valide. J'ai écrit une extension de balisage qui ferait ce que vous voulez. Vous pouvez l'utiliser comme ça:

<TextBlock Text="{my:SwitchBinding MyBoolValue, Yes, No}" /> 

Voici le code pour l'extension de balisage:

public class SwitchBindingExtension : Binding 
{ 
    public SwitchBindingExtension() 
    { 
     Initialize(); 
    } 

    public SwitchBindingExtension(string path) 
     : base(path) 
    { 
     Initialize(); 
    } 

    public SwitchBindingExtension(string path, object valueIfTrue, object valueIfFalse) 
     : base(path) 
    { 
     Initialize(); 
     this.ValueIfTrue = valueIfTrue; 
     this.ValueIfFalse = valueIfFalse; 
    } 

    private void Initialize() 
    { 
     this.ValueIfTrue = Binding.DoNothing; 
     this.ValueIfFalse = Binding.DoNothing; 
     this.Converter = new SwitchConverter(this); 
    } 

    [ConstructorArgument("valueIfTrue")] 
    public object ValueIfTrue { get; set; } 

    [ConstructorArgument("valueIfFalse")] 
    public object ValueIfFalse { get; set; } 

    private class SwitchConverter : IValueConverter 
    { 
     public SwitchConverter(SwitchBindingExtension switchExtension) 
     { 
      _switch = switchExtension; 
     } 

     private SwitchBindingExtension _switch; 

     #region IValueConverter Members 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      try 
      { 
       bool b = System.Convert.ToBoolean(value); 
       return b ? _switch.ValueIfTrue : _switch.ValueIfFalse; 
      } 
      catch 
      { 
       return DependencyProperty.UnsetValue; 
      } 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      return Binding.DoNothing; 
     } 

     #endregion 
    } 

} 
+1

Vous avez raison, ce n'est pas une chaîne de format valide pour une valeur booléenne (elle est valide pour les valeurs numériques). Je testais la chaîne de format comme ceci: string.Format ("{0: Yes ;; No}", 1), qui renvoie "Yes", mais string.Format ("{0: Yes ;; No}", true) renvoie "True". Merci –

+0

Pourriez-vous me suggérer, comment utiliser ElementName lors de la liaison en utilisant ce convertisseur? –

+0

@conqenator, ajoutez simplement 'ElementName = xxx', comme une liaison normale –

53

Vous pouvez également utiliser this great value converter

Ensuite, vous déclarez en XAML quelque chose comme ceci:

<local:BoolToStringConverter x:Key="BooleanToStringConverter" FalseValue="No" TrueValue="Yes" /> 

Et vous pouvez l'utiliser comme ceci:

<TextBlock Text="{Binding Path=MyBoolValue, Converter={StaticResource BooleanToStringConverter}}" /> 
+0

C'est un concept vraiment soigné – pomeroy

+0

Fantastique, merci de partager cela. – GrandMasterFlush

+0

Super! Merci :) –

25

Sans convertisseur

  <TextBlock.Style> 
       <Style TargetType="{x:Type TextBlock}"> 
        <Setter Property="Text" Value="OFF" /> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding MyBoolValue}" Value="True"> 
          <Setter Property="Text" Value="ON" /> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </TextBlock.Style> 
+0

Douceur. Merci. –

+0

J'aime cette solution. Je sais que le convertisseur est une solution commune; Cependant, dans les applications de grande taille, il semble qu'il est préférable de s'attaquer au problème à votre manière (par l'intermédiaire de 'DataTrigger' car vous pourriez vous retrouver avec une tonne de convertisseurs de cas uniques). – Thomas

+1

Vous ne devriez pas avoir un déclencheur pour à la fois vrai et faux, ce n'est pas nécessaire et peut entraîner des problèmes. Vous devez définir un setter par défaut pour la propriété et un seul 'DataTrigger' dans cette instance. –

1

Ceci est un autre convertisseur alternative simplifiée avec "codées en dur" Oui/Non valeurs

[ValueConversion(typeof (bool), typeof (bool))] 
public class YesNoBoolConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var boolValue = value is bool && (bool) value; 

     return boolValue ? "Yes" : "No"; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return value != null && value.ToString() == "Yes"; 
    } 
} 

XAML Utilisation

<DataGridTextColumn Header="Is Listed?" Binding="{Binding Path=IsListed, Mode=TwoWay, Converter={StaticResource YesNoBoolConverter}}" Width="110" IsReadOnly="True" TextElement.FontSize="12" /> 
3

Il est également une autre option vraiment géniale. Cochez celui-ci: Alex141 CalcBinding.

Dans mon DataGrid, je ne dispose que:

<DataGridTextColumn Header="Mobile?" Binding="{conv:Binding (IsMobile?\'Yes\':\'No\')}" /> 

Pour l'utiliser, il suffit d'ajouter le CalcBinding via GitHub, que dans la déclaration UserControl/Windows, vous ajoutez

<Windows XXXXX xmlns:conv="clr-namespace:CalcBinding;assembly=CalcBinding"/> 
0

Ce qui suit a fonctionné pour moi à l'intérieur d'un datatextcolumn: J'ai ajouté une autre propriété à ma classe qui renvoyait une chaîne en fonction de la valeur de MyBool. Notez que dans mon cas, la grille de données était liée à un objet CollectionViewSource de MyClass.

C#:

public class MyClass   
{  
    public bool MyBool {get; set;} 

    public string BoolString  
    {  
     get { return MyBool == true ? "Yes" : "No"; }  
    }  
}   

XAML:

<DataGridTextColumn Header="Status" Binding="{Binding BoolString}"> 
2

C'est une solution en utilisant un Converter et ConverterParameter qui vous permet de définir facilement différents strings pour différentes Bindings:

public class BoolToStringConverter : IValueConverter 
{ 
    public char Separator { get; set; } = ';'; 

    public object Convert(object value, Type targetType, object parameter, 
          CultureInfo culture) 
    { 
     var strings = ((string)parameter).Split(Separator); 
     var trueString = strings[0]; 
     var falseString = strings[1]; 

     var boolValue = (bool)value; 
     if (boolValue == true) 
     { 
      return trueString; 
     } 
     else 
     { 
      return falseString; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
           CultureInfo culture) 
    { 
     var strings = ((string)parameter).Split(Separator); 
     var trueString = strings[0]; 
     var falseString = strings[1]; 

     var stringValue = (string)value; 
     if (stringValue == trueString) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

Définir le C onverter comme ceci:

<local:BoolToStringConverter x:Key="BoolToStringConverter" /> 

Et l'utiliser comme ceci:

<TextBlock Text="{Binding MyBoolValue, Converter={StaticResource BoolToStringConverter}, 
             ConverterParameter='Yes;No'}" /> 

Si vous avez besoin d'un séparateur différent de celui ; (par exemple .), définissez le convertisseur comme ceci:

<local:BoolToStringConverter x:Key="BoolToStringConverter" Separator="." /> 
Questions connexes