144 votes

Lier la visibilité d'un bouton à une valeur bool dans ViewModel

Comment lier la visibilité d'un bouton à une valeur bool dans mon ViewModel ?

<Button Height="50" Width="50" Style="{StaticResource MyButtonStyle}"
    Command="{Binding SmallDisp}" CommandParameter="{Binding}" Cursor="Hand"
    Visibility="{Binding Path=AdvancedFormat}" />

0 votes

Jetez un coup d'œil à CalcBinding

238voto

dlev Points 28160

En supposant que AdvancedFormat est un bool vous devez déclarer et utiliser un BooleanToVisibilityConverter :

<!-- In your resources section of the XAML -->
<BooleanToVisibilityConverter x:Key="BoolToVis" />

<!-- In your Button declaration -->
<Button
 Height="50" Width="50"
 Style="{StaticResource MyButtonStyle}"
 Command="{Binding SmallDisp}" CommandParameter="{Binding}" 
Cursor="Hand" Visibility="{Binding Path=AdvancedFormat, Converter={StaticResource BoolToVis}}"/>

Notez l'ajout de Converter={StaticResource BoolToVis} .

C'est un modèle très courant lorsqu'on travaille avec MVVM. En théorie, vous pourriez effectuer vous-même la conversion sur la propriété ViewModel (c'est-à-dire faire en sorte que la propriété elle-même soit de type Visibility ) bien que je préférerais ne pas le faire, puisque maintenant vous sont en jouant avec la séparation des préoccupations. La visibilité d'un élément devrait vraiment dépendre de la vue.

0 votes

Est-il possible d'utiliser cette méthode si j'utilise un style MVVM ?

2 votes

Bien sûr. Le ViewModel renvoie seulement un booléen, indiquant une condition. Si votre vue interprète ce booléen comme s'il fallait montrer quelque chose ou non, c'est à elle de décider. Notez qu'une autre vue peut toujours l'interpréter différemment.

2 votes

Oui, car il s'agit juste d'une classe d'aide qui masse une valeur. Le viewmodel se situera toujours entre votre modèle et votre vue.

103voto

Robert Rossney Points 43767

Il existe un troisième moyen qui ne nécessite pas de convertisseur ni de modification de votre modèle de vue : l'utilisation d'un style :

<Style TargetType="Button">
   <Setter Property="Visibility" Value="Collapsed"/>
   <Style.Triggers>
      <DataTrigger Binding="{Binding IsVisible}" Value="True">
         <Setter Property="Visibility" Value="Visible"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

J'ai tendance à préférer cette technique parce que je l'utilise dans de nombreux cas où ce que je lie est pas booléen - par exemple, afficher un élément uniquement si son DataContext n'est pas nulle, ou la mise en œuvre d'affichages à états multiples où différentes mises en page apparaissent en fonction de la configuration d'un enum dans le modèle de vue.

6 votes

En général, j'ai l'impression que les convertisseurs sont des bidouillages et je ne les aime pas. Je pense que c'est plus une question de goût personnel grincheux qu'une évaluation sobre des avantages et inconvénients d'un point de vue technique, mais je les évite.

1 votes

Je ne peux pas dire que je les utilise si souvent non plus. Ils ont tendance à être un peu capricieux (sic ?). Après votre message, je me suis souvenu que j'avais utilisé un certain nombre de styles/déclencheurs dans des projets précédents...

0 votes

J'avais un TextBlock à laquelle TextWrapping="Wrap" a été donné. Maintenant, cette propriété d'emballage n'y est pas fixée.

11voto

Berty Points 171

Conversion à 2 voies en c# de booléen à visibilité

using System;
using System.Windows;
using System.Windows.Data;

namespace FaceTheWall.converters
{
    class BooleanToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Boolean && (bool)value)
            {
                return Visibility.Visible;
            }
            return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Visibility && (Visibility)value == Visibility.Visible)
            {
                return true;
            }
            return false;
        }
    }
}

7 votes

Comme cela a déjà été mentionné, il en existe un déjà intégré à WPF. Vous n'avez pas besoin de créer le vôtre.

4voto

CodeWarrior Points 3541

En général, il y a deux façons de procéder : une classe de conversion ou une propriété dans le modèle de vue qui convertit essentiellement la valeur pour vous.

J'ai tendance à utiliser l'approche immobilière s'il s'agit d'une conversion unique. Si vous voulez la réutiliser, utilisez le convertisseur. Ci-dessous, vous trouverez un exemple de convertisseur :

<ValueConversion(GetType(Boolean), GetType(Visibility))> _
Public Class BoolToVisibilityConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert

        If value IsNot Nothing Then
            If value = True Then 
                Return Visibility.Visible
            Else
                Return Visibility.Collapsed
            End If
        Else
            Return Visibility.Collapsed
        End If
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException
    End Function
End Class

Une méthode de propriété ViewModel vérifierait simplement la valeur de la propriété booléenne et renverrait une visibilité en fonction de celle-ci. Assurez-vous d'implémenter INotifyPropertyChanged et de l'appeler à la fois sur les propriétés booléennes et de visibilité afin de les mettre à jour correctement.

14 votes

WPF dispose déjà d'un BooleanToVisibilityConverter construit.

0 votes

Je ne l'avais pas réalisé. Celui-ci était en fait quelque chose d'autre que j'ai modifié pour l'adapter à ce scénario. Tant mieux s'il y en a un de pré-construit.

2voto

Kevin Points 1182

En vue :

<Button
 Height="50" Width="50"
 Style="{StaticResource MyButtonStyle}"
 Command="{Binding SmallDisp}" CommandParameter="{Binding}" 
Cursor="Hand" Visibility="{Binding Path=AdvancedFormat}"/>

En vue Modèle :

public _advancedFormat = Visibility.visible (whatever you start with)

public Visibility AdvancedFormat
{
 get{return _advancedFormat;}
 set{
   _advancedFormat = value;
   //raise property changed here
}

Vous aurez besoin d'un événement de changement de propriété

 protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
        PropertyChanged.Raise(this, e); 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
    } 

Voici comment ils utilisent Model-view-viewmodel

Mais comme vous voulez qu'il soit lié à un booléen, vous aurez besoin d'un convertisseur. Une autre solution consiste à définir un booléen à l'extérieur et, lorsque le bouton est cliqué, à définir la propriété_advancedFormat sur la visibilité souhaitée.

0 votes

private Visibility _advancedFormat = Visibility.visible Cela fonctionne bien sur UWP Merci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X