2010-12-14 73 views
6

J'ai une case à cocher 'Tout sélectionner' que je voudrais être lié à la (IsChecked ||! IsEnabled) des autres cases à cocher.WPF Bind Case à cocher IsChecked à d'autres cases à cocher (IsChecked ||! IsEnabled)

  • Cochez toutes les cases cochées toutes activées. Si vous décochez "Toutes", toutes les cases à cocher sont décochées.

  • La vérification manuelle de chaque case cochée permet de cocher la case «Tous».

  • Lorsque toutes les cases activées et «Tous» sont cochées et que l'utilisateur décoche une case, «Tous» désélectionne automatiquement.

Je suis nouveau à WPF Databinding. Je pensais peut-être que je faisais juste le clic de 'Tout' pour mettre les autres cases à cocher. Mais je ne sais pas comment lier les deux propriétés de plusieurs sources. Lorsque je clique sur «Tous» et que je désélectionne une autre case, «Tous» doit être décochée.

Répondre

12

Voici une façon de le faire dans Xaml avec des convertisseurs. Cela suppose que tous vos CheckBox sont ajoutés directement en tant que contrôles dans Xaml (ce n'est pas très dynamique, ne fonctionnera pas pour DataTemplate, etc). D'abord nous créons trois CheckBoxes (CheckBox1, CheckBox2, CheckBox3) qui seront vérifiés/non cochés lors de la vérification de CheckAllCheckBox. Cela fonctionnera également en sens inverse.

Mise à jour
La dernière partie (ignorer CheckBox désactivé) était un peu un problème et je ne suis pas fou de cette solution, mais je ne vois pas une meilleure façon. Nous stockons les valeurs de Convert et les réutilisons dans ConvertBack pour les CheckBox désactivés. Faire cela, il faut aussi ajouter le x: Shared = attribut « False » pour le CheckAllConverter depuis une nouvelle instance est nécessaire pour chaque MultiBinding qui l'utiliser (peu probable dans ce cas, mais encore ..)

<Window.Resources> 
    <local:CheckAllConverter x:Key="CheckAllConverter" x:Shared="False"/> 
</Window.Resources> 
<StackPanel> 
    <CheckBox Content="Check All" 
       Name="CheckAllCheckBox"> 
     <CheckBox.IsChecked> 
      <MultiBinding Converter="{StaticResource CheckAllConverter}"> 
       <Binding ElementName="CheckBox1" Path="IsChecked" /> 
       <Binding ElementName="CheckBox1" Path="IsEnabled" Mode="OneWay"/> 
       <Binding ElementName="CheckBox2" Path="IsChecked" /> 
       <Binding ElementName="CheckBox2" Path="IsEnabled" Mode="OneWay"/> 
       <Binding ElementName="CheckBox3" Path="IsChecked" /> 
       <Binding ElementName="CheckBox3" Path="IsEnabled" Mode="OneWay"/> 
      </MultiBinding> 
     </CheckBox.IsChecked> 
    </CheckBox> 
    <CheckBox Content="CheckBox 1" 
       Name="CheckBox1"/> 
    <CheckBox Content="CheckBox 2" 
       Name="CheckBox2"/> 
    <CheckBox Content="CheckBox 3" 
       Name="CheckBox3"/> 
</StackPanel> 

Le Convertisseur pour CheckAll

public class CheckAllConverter : IMultiValueConverter 
{ 
    private object[] convertValues = null; 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     convertValues = new object[values.Length]; 
     for(int i = 0; i < values.Length; i++) 
     { 
      convertValues[i] = values[i]; 
     } 

     for (int i = 0; i < values.Length; i += 2) 
     { 
      bool isChecked = (bool)values[i]; 
      bool isEnabled = (bool)values[i + 1]; 
      if (isEnabled == false) 
      { 
       continue; 
      } 
      if (isChecked == false) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     object[] values = new object[targetTypes.Length]; 
     for (int i = 0; i < values.Length; i += 2) 
     { 
      if (convertValues != null && (bool)convertValues[i + 1] == false) 
      { 
       values[i] = convertValues[i]; 
      } 
      else 
      { 
       values[i] = value; 
      } 
      // IsEnabled is OneWay and won't care about this value 
      values[i + 1] = null; 
     } 
     return values; 
    } 
} 
+0

C'est génial. Je n'ai pas besoin de la case à cocher décocher ou l'autre convertisseur et j'ai retiré le déclencheur pour désactiver. Cependant, j'aimerais permettre que les autres cases à cocher puissent être désactivées. Ils ne devraient pas être vérifiés lorsqu'ils sont désactivés, mais ils ne seront pas pris en compte dans le contrôle total. Par exemple. Si la case à cocher 2 est désactivée, cliquer sur Vérifier tout ne la vérifie pas. Et si la case à cocher 1/3 est cochée, tout cocher devient coché. – TrevDev

+0

Oui, c'est ce que je pensais :) Une case à cocher devrait le faire puisque cela fonctionne dans les deux sens, j'ai mal lu la question. Je vais mettre à jour ma réponse et regarder dans vos commentaires –

+0

Merci! J'ai commencé à jouer avec ce que tu as donné. Je l'ai rendu mal à l'aise en faisant une liaison à sens unique à la propriété IsEnabled. Lors de la conversion d'une case non cochée, je vérifie i + 1 pour la propriété oneway enabled heh. C'est désordonné et je n'ai pas vu un moyen d'ignorer les cases à cocher désactivées lors de la conversion en arrière. Je suis curieux de voir votre solution proposée. – TrevDev

1

Je créerais un ViewModel derrière votre classe View en utilisant le design pattern MVVM: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

ensuite sur votre ViewModel (qui devra mettre en œuvre INotifyPropertyChanged) vous pouvez avoir plusieurs bool propriétés, un pour chaque CheckBox et un autre pour chacun d'eux:

public bool IsChecked1 
{ 
    get 
    { 
     return isChecked1; 
    } 
    set 
    { 
     if (isChecked1 != value) 
     { 
      isChecked1 = value; 
      RaisePropertyChanged("IsChecked1"); 
      RaisePropertyChanged("AreAllChecked"); 
     } 
    } 
} 

// And so on 

public bool AreAllChecked 
{ 
    get 
    { 
     return IsChecked1 && IsChecked2; // etc. 
    } 
    set 
    { 
     if (AreAllChecked != value) 
     { 
      IsChecked1 = value; 
      IsChecked2 = value; 
      // etc. 
     } 
    } 
} 
+0

Pas une bonne solution IMO. Et s'il y a 50 cases à cocher? –