web-dev-qa-db-fra.com

MultiDataTrigger avec OR au lieu de AND

J'essaie de définir plusieurs DataTriggers sur mon Button. J'ai fait quelques recherches et j'ai découvert que MultiDataTrigger vous permet de le faire. Je souhaite que la propriété Visibility de mon Button soit définie sur false si le CCTVPath == string.Empty OR PermissionsFlag == false. C'est ce que j'ai jusqu'à présent;

<Button Grid.Column="3" x:Name="cctvFeedButton" Content="Live Feed"
        Width="100" FontSize="16" HorizontalAlignment="Right" Margin="5" Click="OnCCTVButtonClick">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding CCTVPath}" Value=""/>
                        <Condition Binding="{Binding PermissionsFlag}" Value="False"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Visibility" Value="Hidden"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Et dans mon code-behind j'ai mis PermissionsFlag comme ça;

public bool PermissionsFlag { get; set; }

private void OnPageLoaded(object sender, RoutedEventArgs e)
{
    PermissionsFlag = false;
}

Comme vous pouvez le voir, PermissionsFlag est définitivement faux, et il y a définitivement CCTVPath mais le Button n'est jamais caché. Qu'est-ce que je fais mal?

MISE À JOUR:

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private bool _permissionsFlag;
    public bool Flag
    {
        get { return _permissionsFlag; }
        set
        {
            _permissionsFlag = value;
            OnPropertyChanged("PermissionsFlag");
        }
    }

    private void OnPageLoaded(object sender, RoutedEventArgs e)
    {
        Flag = false;
        CCTVImageCollection = GetImages();
        imageListBox.ItemsSource = CCTVImageCollection;
        DataContext = this;
    }

Dans mon XAML:

<Button.Style>
         <Style TargetType="Button">
               <Style.Triggers>
                      <DataTrigger Binding="{Binding PermissionsFlag}" Value="False">
                            <Setter Property="Visibility" Value="Hidden"/>
                      </DataTrigger>
               </Style.Triggers>
         </Style>
 </Button.Style>
17
CBreeze

Une solution alternative consiste à utiliser un seul DataTrigger avec un MultiBinding. Vous pouvez le faire fonctionner en définissant un IMultiValueConverter de `` cas spécial '' qui suppose 2 éléments dans le tableau d'objets et renvoie vrai si le premier élément est une chaîne vide OR le deuxième élément est faux. Cependant, vous n'utiliserez probablement jamais ce convertisseur ailleurs dans votre code. Donc, si vous êtes prêt à faire un peu plus de travail à l'avance, vous pouvez définir 3 convertisseurs simples/réutilisables.

1) un [IMultiValueConverter] 'OrConverter', qui ressemblerait à ceci:

public class BooleanOrConverter : IMultiValueConverter {
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
      return values.OfType<bool>().Any(b => b);
   }

   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
      throw new NotImplementedException();
   }
}

2) Un convertisseur de chaîne [IValueConverter] 'IsNullOrEmpty':

public class StringIsNullOrEmptyConverter : IValueConverter {
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
      return string.IsNullOrEmpty(value as string);
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
      throw new NotImplementedException();
   }
}

3) Et un [IValueConverter] 'NotConverter:'

public class BooleanNotConverter : IValueConverter {
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
      return !(bool)value;
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
      throw new NotImplementedException();
   }
}

Ensuite, dans votre xaml, le DataTrigger serait défini comme ceci:

<Button x:Name="cctvFeedButton" Content="Live Feed"
  Width="100" FontSize="16" HorizontalAlignment="Right" Margin="5">
  <Button.Style>
    <Style TargetType="Button">
      <Style.Triggers>
         <DataTrigger Value="True">
           <DataTrigger.Binding>
             <MultiBinding Converter="{StaticResource OrConverter}">
               <Binding Path="PermissionFlag" Converter="{StaticResource NotConverter}"/>
               <Binding Path="CCTVPath" Converter="{StaticResource IsNullOrEmptyConverter}"/>
             </MultiBinding>
           </DataTrigger.Binding>
           <Setter Property="Visibility" Value="Hidden"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Button.Style>
</Button>

Je préfère cette solution à l'utilisation de 2 DataTriggers séparés pour la lisibilité; il exprime mieux le comportement que vous définissez - c'est la logique "ou": un ensemble singulier de 2 conditions qui devraient masquer le bouton.

1
John Colvin