Comment lier les propriétés booléennes inverses dans WPF?

Ce que j’ai est un object qui a une propriété IsReadOnly . Si cette propriété est true, j’aimerais définir la propriété IsEnabled sur un bouton (par exemple) sur false.

Je voudrais croire que je peux le faire aussi facilement que IsEnabled="{Binding Path=!IsReadOnly}" mais cela ne vole pas avec WPF.

Suis-je relégué à devoir parcourir tous les parameters de style? Juste semble trop verbeux pour quelque chose d’aussi simple que de mettre un bool à l’inverse d’un autre bool.

  

Vous pouvez utiliser un ValueConverter qui inverse une propriété bool pour vous.

XAML:

 IsEnabled="{Binding Path=IsReadOnly, Converter={StaticResource InverseBooleanConverter}}" 

Convertisseur:

 [ValueConversion(typeof(bool), typeof(bool))] public class InverseBooleanConverter: IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (targetType != typeof(bool)) throw new InvalidOperationException("The target must be a boolean"); return !(bool)value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotSupportedException(); } #endregion } 

Avez-vous envisagé une propriété IsNotReadOnly? Si l’object lié est un ViewModel dans un domaine MVVM, la propriété supplémentaire prend tout son sens. S’il s’agit d’un modèle d’entité direct, vous pouvez envisager la composition et présenter un modèle de vue spécialisé de votre entité au formulaire.

Avec une liaison standard, vous devez utiliser des convertisseurs peu venteux. Donc, je vous recommande de regarder mon projet CalcBinding , qui a été développé spécialement pour résoudre ce problème et d’autres. Avec la liaison avancée, vous pouvez écrire des expressions avec de nombreuses propriétés source directement dans xaml. Dis, tu peux écrire quelque chose comme:

  

ou

  

ou

  

ou

  

où A, B, C, IsChecked – propriétés de viewModel et cela fonctionnera correctement

Bonne chance!

Je recommande d’utiliser https://quickconverter.codeplex.com/

Inverser un booléen est alors aussi simple que:

Cela accélère le temps normalement nécessaire pour écrire les convertisseurs.

Je voulais que mon XAML rest aussi élégant que possible, alors j’ai créé une classe pour envelopper le bool qui réside dans l’une de mes bibliothèques partagées, les opérateurs implicites permettent à la classe d’être utilisée comme une valeur booléenne dans le code

 public class InvertableBool { private bool value = false; public bool Value { get { return value; } } public bool Invert { get { return !value; } } public InvertableBool(bool b) { value = b; } public static implicit operator InvertableBool(bool b) { return new InvertableBool(b); } public static implicit operator bool(InvertableBool b) { return b.value; } } 

Les seuls changements nécessaires à votre projet sont de faire en sorte que la propriété que vous souhaitez inverser renvoie ceci au lieu de bool

  public InvertableBool IsActive { get { return true; } } 

Et dans le postfix XAML la liaison soit avec valeur ou inverser

 IsEnabled="{Binding IsActive.Value}" IsEnabled="{Binding IsActive.Invert}" 

Celui-ci fonctionne également pour les bools nulles.

  [ValueConversion(typeof(bool?), typeof(bool))] public class InverseBooleanConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (targetType != typeof(bool?)) { throw new InvalidOperationException("The target must be a nullable boolean"); } bool? b = (bool?)value; return b.HasValue && !b.Value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return !(value as bool?); } #endregion } 

Je ne sais pas si cela est pertinent pour XAML, mais dans ma simple application Windows, j’ai créé la liaison manuellement et ajouté un gestionnaire d’événements Format.

 public FormMain() { InitializeComponent(); Binding argBinding = new Binding("Enabled", uxCheckBoxArgsNull, "Checked", false, DataSourceUpdateMode.OnPropertyChanged); argBinding.Format += new ConvertEventHandler(Binding_Format_BooleanInverse); uxTextBoxArgs.DataBindings.Add(argBinding); } void Binding_Format_BooleanInverse(object sender, ConvertEventArgs e) { bool boolValue = (bool)e.Value; e.Value = !boolValue; } 

Ajoutez une propriété supplémentaire dans votre modèle de vue, qui renverra une valeur inverse. Et liez cela au bouton. Comme;

dans le modèle de vue:

 public bool IsNotReadOnly{get{return !IsReadOnly;}} 

dans xaml:

 IsEnabled="{Binding IsNotReadOnly"} 

J’ai eu un problème d’inversion, mais une solution soignée.

La motivation était que le concepteur XAML afficherait un contrôle vide, par exemple quand il n’y avait pas de contexte de données / pas de MyValues (itemssource).

Code initial: cache le contrôle lorsque MyValues est vide. Code amélioré: affiche le contrôle lorsque MyValues n’est PAS nul ou vide.

Bien sûr, le problème est de savoir comment exprimer «1 ou plusieurs articles», ce qui est le contraire de 0 éléments.

      

Je l’ai résolu en ajoutant:

  

Ergo définissant la valeur par défaut pour la liaison. Bien sûr, cela ne fonctionne pas pour toutes sortes de problèmes inverses, mais m’a aidé avec du code propre.

Après la réponse de Paul, j’ai écrit ce qui suit dans le ViewModel:

 public bool ShowAtView { get; set; } public bool InvShowAtView { get { return !ShowAtView; } } 

J’espère qu’avoir un extrait ici aidera quelqu’un, probablement un débutant tel que je suis.
Et s’il y a une erreur, faites-le moi savoir!

BTW, je suis également d’accord avec @heltonbiker comment – c’est certainement la bonne approche que si vous n’avez pas à l’utiliser plus de 3 fois …

J’ai fait quelque chose de très similaire. J’ai créé ma propriété dans les coulisses, ce qui a permis de sélectionner une liste déroulante UNIQUEMENT si elle avait fini de rechercher des données. Lorsque ma fenêtre apparaît pour la première fois, une commande asynchrone est lancée, mais je ne souhaite pas que l’utilisateur clique sur la liste déroulante pendant le chargement des données (serait vide, puis remplie). Donc, par défaut, la propriété est fausse donc je retourne l’inverse dans le getter. Ensuite, lorsque je cherche, je mets la propriété à true et reviens à false à la fin.

 private bool _isSearching; public bool IsSearching { get { return !_isSearching; } set { if(_isSearching != value) { _isSearching = value; OnPropertyChanged("IsSearching"); } } } public CityViewModel() { LoadedCommand = new DelegateCommandAsync(LoadCity, LoadCanExecute); } private async Task LoadCity(object pArg) { IsSearching = true; //**Do your searching task here** IsSearching = false; } private bool LoadCanExecute(object pArg) { return IsSearching; } 

Ensuite, pour la liste déroulante, je peux le lier directement à IsSearching: