2010-12-14 12 views
6

Ho una casella di controllo "Tutti" che desidero essere associata a (IsChecked ||! IsEnabled) di altre checkbox.WPF Bind Checkbox IsChecked ad altre caselle di controllo (IsChecked ||! IsEnabled)

  • Il controllo "Tutti" controlla tutte le caselle abilitate.

  • Deselezionando 'Tutti' deseleziona tutte le caselle di controllo.

  • Controllare manualmente ogni casella di controllo abilitato controllerà "Tutto".

  • Quando tutte le caselle di controllo abilitate e "Tutto" sono selezionate e l'utente deseleziona qualsiasi casella di controllo, "Tutto" deseleziona automaticamente.

Sono nuovo al Databinding WPF. Stavo pensando che forse mi limito a gestire il clic di "Tutti" per impostare le altre caselle di controllo. Ma non so come legare a entrambe le proprietà di più fonti. Quando faccio clic su "Tutti" e deseleziono manualmente un'altra casella, "Tutto" deve deselezionare.

risposta

12

Ecco un modo per farlo in Xaml con Convertitori. Ciò presuppone che tutti i tuoi CheckBox vengano aggiunti direttamente come Controlli in Xaml (non è molto dinamico, non funzionerà per il DataTemplate, ecc.). Per prima cosa creiamo tre CheckBox (CheckBox1, CheckBox2, CheckBox3) che saranno spuntati/Deselezionati quando si controlla CheckAllCheckBox. Funzionerà anche al contrario.

Aggiornamento
L'ultima parte (ignorare CheckBox disabile) è stato un po 'un problema qui e io non sono pazzo di questa soluzione, ma non riesco a vedere un modo migliore. Memorizziamo i valori da Converti e li riutilizziamo in ConvertBack per i CheckBox disabilitati. Facendo questo, dobbiamo anche aggiungere l'x: Shared = attributo "False" per il CheckAllConverter poiché è richiesta una nuova istanza per ogni MultiBinding che usarlo (improbabile in questo caso, ma ancora ..)

<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> 

Il Convertitore per 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

Questo è fantastico. Non avevo bisogno della casella di controllo deseleziona o dell'altro convertitore e ho rimosso il trigger per disabilitare. Tuttavia, vorrei consentire che le altre caselle di controllo siano disabilitate. Non dovrebbero essere controllati quando disabilitati ma non contano per il controllo di tutti. Ad esempio. Se Checkbox 2 è disabilitato, fare clic su Controlla tutto non lo controlla. E se I Checkbox1/3 è selezionato, Seleziona tutto diventa selezionato. – TrevDev

+0

Sì, questo è quello che pensavo :) Una casella di controllo dovrebbe farlo poiché funziona in entrambi i modi, ho missread la domanda. Aggiornerò la mia risposta e guarderò nei tuoi commenti –

+0

Grazie! Ho iniziato a giocare con ciò che hai dato. L'ho reso incasinato creando un legame unidirezionale con la proprietà IsEnabled. Quando si converte una casella di controllo deselezionata, controllo i + 1 per la proprietà abilitata oneway heh. È disordinato e non ho visto un modo per ignorare le caselle di controllo disattivate durante la conversione. Sono curioso di vedere la tua soluzione proposta. – TrevDev

1

mi piacerebbe creare un ViewModel dietro la classe View utilizzando il modello di progettazione MVVM: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

Poi sul tuo ViewModel (che dovrà implementare INotifyPropertyChanged) è possibile avere più bool proprietà, uno per ogni CheckBox e un altro per tutti:

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

Non una buona soluzione IMO. Cosa succede se ci sono 50 checkbox? –