2010-12-14 30 views
6

Tôi có một hộp kiểm 'Tất cả' chọn mà tôi muốn bị ràng buộc vào hộp kiểm (IsChecked ||! IsEnabled) của các hộp kiểm khác.Hộp kiểm WPF Bind được đánh dấu vào các hộp kiểm khác (IsChecked ||! IsEnabled)

  • Đánh dấu chọn 'Tất cả' kiểm tra tất cả các hộp kiểm đã bật.

  • Bỏ chọn 'Tất cả' bỏ chọn tất cả các hộp kiểm.

  • Kiểm tra thủ công từng hộp kiểm đã bật sẽ kiểm tra 'Tất cả'.

  • Khi tất cả hộp kiểm được bật và 'Tất cả' được chọn và người dùng bỏ chọn bất kỳ hộp kiểm nào, 'Tất cả' sẽ tự động bỏ chọn.

Tôi mới vào WPF Databinding. Tôi đã suy nghĩ có lẽ tôi chỉ xử lý các nhấp chuột của 'Tất cả' để thiết lập các hộp kiểm khác. Nhưng tôi không biết cách liên kết với cả hai thuộc tính của nhiều nguồn. Khi tôi nhấp vào 'Tất cả' và bỏ chọn hộp kiểm khác theo cách thủ công, 'Tất cả' cần bỏ chọn.

Trả lời

12

Đây là cách để thực hiện trong Xaml bằng Trình chuyển đổi. Điều này giả định rằng tất cả các CheckBox của bạn được thêm trực tiếp như Controls trong Xaml (nó không phải là rất năng động, sẽ không làm việc cho DataTemplate's etc). Đầu tiên chúng ta tạo 3 CheckBox (CheckBox1, CheckBox2, CheckBox3) sẽ được Checked/Unchecked khi Checking CheckAllCheckBox. Nó cũng sẽ làm việc ngược lại.

Cập nhật
Phần cuối cùng (bỏ qua khuyết tật CheckBox) là một chút của một vấn đề ở đây và tôi không phát điên lên vì giải pháp này nhưng tôi không thể nhìn thấy một cách tốt hơn. Chúng tôi lưu trữ các giá trị từ chuyển đổi và tái sử dụng chúng trong ConvertBack cho CheckBox của người tàn tật. Việc làm này, chúng ta cũng nên thêm x: Shared = thuộc tính "False" cho CheckAllConverter từ một trường hợp mới là cần thiết cho mỗi MultiBinding rằng sẽ sử dụng nó (không trong trường hợp này nhưng vẫn ..)

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

Các Bộ chuyển đổi cho 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

Điều này thật tuyệt. Tôi không cần hộp kiểm bỏ chọn hoặc trình chuyển đổi khác và tôi đã xóa trình kích hoạt để tắt. Tuy nhiên, tôi muốn cho phép các hộp kiểm khác có thể bị vô hiệu hóa. Họ không nên trở thành kiểm tra khi bị vô hiệu hóa nhưng họ sẽ không tính vào kiểm tra tất cả. Ví dụ. Nếu Checkbox 2 bị vô hiệu hóa, việc nhấp vào Check All sẽ không kiểm tra. Và nếu tôi Checkbox1/3 được chọn, Check All sẽ được chọn. – TrevDev

+0

Vâng, đó là những gì tôi nghĩ :) Một hộp kiểm nên làm điều đó vì nó hoạt động cả hai cách, tôi bỏ lỡ câu hỏi. Tôi sẽ cập nhật câu trả lời của tôi và xem xét ý kiến ​​của bạn –

+0

Cảm ơn! Tôi bắt đầu chơi với những gì bạn đã đưa ra. Tôi đã làm cho nó lộn xộn bằng cách thực hiện một cách ràng buộc với tài sản IsEnabled. Khi chuyển đổi một hộp kiểm bỏ chọn, tôi kiểm tra i + 1 cho thuộc tính được kích hoạt on heh. Của nó lộn xộn và tôi đã không nhìn thấy một cách để bỏ qua hộp kiểm vô hiệu hóa khi chuyển đổi trở lại. Tôi rất tò mò muốn xem giải pháp được đề xuất của bạn. – TrevDev

1

Tôi muốn tạo ra một ViewModel đằng sau Xem lớp học của bạn bằng cách sử dụng mẫu thiết kế MVVM: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

Sau đó, trên bạn ViewModel (mà sẽ phải thực hiện INotifyPropertyChanged), bạn có thể có nhiều bool tài sản, một cho mỗi CheckBox và khác cho tất cả chúng:

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

Không phải là giải pháp tốt IMO. Nếu có 50 hộp kiểm thì sao? –

Các vấn đề liên quan