如何在WPF中设置/重置三态复选框值

时间:2011-01-24 03:04:48

标签: wpf wpf-controls checkbox wpfdatagrid

我有一个数据网格,其中一个标题列是三态复选框。该列的celltemplate包含两个状态复选框 + AllItems CheckBox    - 第1项    - 第2项    - 第3项    .. 我想使用AllItems复选框来选择/取消选择工作正常的所有项目(item1,item2)。接下来,我想在未选择/取消选择所有项目时将AllItems复选框设置为中间状态。同样,当手动选择所有项目时,我想将AllItems复选框设置为选中/取消选中。

这是我试过的代码......

<dg:DataGridTemplateColumn.HeaderTemplate>
    <DataTemplate>
        <StackPanel x:Name="StackPanelForItemCheckbox" Orientation="Horizontal">
           <CheckBox x:Name="AllItemSelectionCheckBox" HorizontalAlignment="Left" Cursor="Hand"  
                     IsChecked="{Binding IsAllItemChecked, Mode=TwoWay}"                                              
                     IsThreeState="True"  Checked="ItemSelectionCheckBox_Checked" 
                     Unchecked="ItemSelectionCheckBox_Unchecked"
                     Click="AllItemSelectionCheckBox_Click">
           <TextBlock x:Name="ItemNameTextBlock" Text="Item" Margin="10,0,0,0">
           ......
<dg:DataGridTemplateColumn.CellTemplate>
       <DataTemplate x:Name="ItemCheckDataTemplate">                                
           <StackPanel x:Name="ItemCheckBoxStackPanel" Orientation="Horizontal">                                    
                  <CheckBox x:Name="itemCheckBox" Cursor="Hand" IsChecked="{Binding IsItemChecked, Mode=TwoWay}" Click="ItemSelectionCheckBox_Click"></CheckBox>
                   <TextBlock x:Name="ItemNameTextBlock" Text="{Binding Path=Item}"> </TextBlock>                                   
            </StackPanel>
         </DataTemplate>
...

“ItemSelectionCheckBox_Click”方法查找所有三种状态(全部检查,未检查,中间)并设置“IsAllItemChecked”属性,即INotifyproperty。这是行不通的。我可能尝试的其他替代方法是找到“AllItems”元素并从代码中设置它。无法在网络上找到类似的内容。几乎没有例子,但TreeView并不是我尝试的方式。有什么帮助吗?

PS&GT;&GT;

更新了修复以关闭此帖子。

  • 我想要的第一件事是在手动选择时允许“AllItemSelectionCheckBox”只有两个状态(True,False)。

    private void AllItemSelectionCheckBox_Click(object sender, RoutedEventArgs e)
    {
        var cb = e.Source as CheckBox;
        if (!cb.IsChecked.HasValue)
            cb.IsChecked = false;  
    }
    
  • 我希望“AllItemSelectionCheckBox”复选框显示三态直通代码。
  • 选中所有复选框将使其值为TRUE
  • 未选中所有复选框将导致其值为FALSE
  • 任何选定的选项都会导致其值为NULL。

以下代码示例:

private void itemCheckBox_Checked(object sender, RoutedEventArgs e)
{ 
    DataGridRowsPresenter DGRPresenter = FindVisualChild<DataGridRowsPresenter>(DataGName1);
    if (DGRP == null || DGRP.Children == null)
        return null;
    foreach (object obj in UIEC)
    {
        DGR = obj as Microsoft.Windows.Controls.DataGridRow;
        UIC = DGR.Item as <datagrid mapped data model>;
        if (DGR.IsSelected == true)
            UIC.IsItemChecked = true;
        if (UIC.IsItemChecked == true)
                NumberOfItemsChecked++;
    }
    if (NumberOfItemsChecked == myViewModelAllItems.Count)
    {
        allcheckbox.IsChecked = true;
    }
    else if (NumberOfItemsChecked < myViewModelAllItems.Count)
    {
        allcheckbox.IsChecked = null;   //intermittent state
    }
}

全局更新NumberOfItemsChecked计数由于竞争条件破坏了外部值而无效。

注意:上面的代码更像是一个例子,可能无法直接复制它。我可以根据要求提供完整的代码样本。

4 个答案:

答案 0 :(得分:13)

实际上我有一个更好。

我发现如果我为IsThreeState创建一个绑定,然后根据值是否设置更改值,那么它就可以工作。

bool? _Value;
public bool? Value
{
    get { return _Value; }
    set
    {
        if (value == null)
        {
            IsThreeState = true;
        }
        else
        {
            IsThreeState = false;
        }
        _Value = value;

        NotifyPropertyChanged("Value");
    }
}

bool _IsThreeState = true;
public bool IsThreeState
{
    get { return _IsThreeState; }
    private set
    {
        _IsThreeState = value;
        NotifyPropertyChanged("IsThreeState");
    }
}

现在该复选框将支持三态IFF,该值在外部设置为null。 如果值为true或false,则用户将无法将其设置为null。

答案 1 :(得分:1)

我找到了一个简单的方法:

调整事件单击三个状态复选框,并检查其值是否为空。如果确实将其更改为false。像这样:

private void cbAllFeatures_Click(object sender, RoutedEventArgs e)
    {
        CheckBox checkbox = sender as CheckBox;
        if (checkbox.IsChecked == null)
            checkbox.IsChecked = false;
    }

我希望你喜欢它。

答案 2 :(得分:0)

这对我有用。我创建了一个新的FTThreeStateCheckBox(从CheckBox子类化),覆盖了IsCheckedProperty元数据,因此我可以监视值的变化,然后如果它为null,我将IsThreeState和IsChecked设置为false。

import FacebookCore

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)

    return true
  }

  func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {

    if let _ = Bundle.main.object(forInfoDictionaryKey: "FacebookAppID") as? String {
      return SDKApplicationDelegate.shared.application(application,
                                                       open: url,
                                                       sourceApplication: sourceApplication,
                                                       annotation: annotation)
    }

      return false
    }

  @available(iOS 9.0, *)
  func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {

    if let _ = Bundle.main.object(forInfoDictionaryKey: "FacebookAppID") as? String {
      return SDKApplicationDelegate.shared.application(application, open: url, options: options)
    }

      return false
  }
}

答案 3 :(得分:0)

针对想要实现这一目标的人

  • 用户只能将视图中的复选框切换为true或false。不要不确定!
  • ViewModel中的代码应能够将复选框切换为未定义

只需这样做:

  • 添加复选框进行查看,但不要设置IsThreeState=true
  • IsChecked绑定到ViewModel中的bool?(可空布尔)属性

您现在可以在ViewModel中将其设置为null,而用户不能在View中进行设置。

相关问题