如何在 WPF 中设置/重置三态复选框值
我有一个数据网格,其标题列之一是三态复选框。该列的单元格模板包含两个状态复选框 + 所有项目复选框 - 项目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>>
更新并修复以关闭此帖子。
我想要的第一件事是允许“AllItemSelectionCheckBox”在手动选择时只有两种状态(True、False)。
private void AllItemSelectionCheckBox_Click(对象发送者, 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 计数不起作用。
注意:上面的代码更像是一个示例,直接复制它可能不起作用。我可以根据要求提供完整的代码和示例。
I have a datagrid whose one of the header column is Three-state checkbox. The celltemplate for that column contains two state checkbox
+ AllItems CheckBox
- Item1
- Item2
- Item3
..
I wanted to use AllItems checkbox to select/unselect all items (item1,item2) which works fine. Next I wanted to set AllItems checkbox to intermediate state when not all items are selected/unselected. Similarly I wanted to set AllItems checkbox as checked/unchecked when all items get manually selected.
Here is the code that I tried...
<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" method looks for all three state (all-checked, none-checked, intermediate) and sets "IsAllItemChecked" property which is INotifyproperty. It does not work. Other alternative I may try is to find the "AllItems" element and set it from the code. Could not locate anything like that on web. There is few examples but is for TreeView and not the way I am trying. Any help?
PS>>
Updated with fix to close this post.
First thing I wanted was to allow "AllItemSelectionCheckBox" to have only two states (True, False) when manually selected.
private void AllItemSelectionCheckBox_Click(object sender, RoutedEventArgs e) { var cb = e.Source as CheckBox; if (!cb.IsChecked.HasValue) cb.IsChecked = false; }
- I wanted "AllItemSelectionCheckBox" checkbox to show three-state thru code.
- All check-box checked will cause its value to TRUE
- All check-box unchecked will cause its value to FALSE
- Any few selected will cause its value to NULL.
Code Example following:
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
}
}
Updating NumberOfItemsChecked count globally did not work due to race condition corrupting the value outside.
Note: Above code is more like an example and may not work copying it directly. I can provide complete code with sample on request.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这对我有用。我创建了一个新的 FTThreeStateCheckBox(CheckBox 的子类),覆盖 IsCheckedProperty 元数据,以便我可以监视值的更改,然后如果它为 null,我将 IsThreeState 和 IsChecked 设置为 false。
This is what worked for me. I created a new FTThreeStateCheckBox (subclassed from CheckBox), overrode the IsCheckedProperty metadata so I could watch for changes in the value, then if it was null, I set IsThreeState and IsChecked to false.
我找到了一个简单的方法:
调整三态复选框的事件点击,并检查其值是否为空。如果确实将其更改为 false。就像这样:
我希望你喜欢它。
I found a simple way:
Adjust the event click of three state check box, and check if its value is null. If does change it to false. Like this:
I hope you enjoy it.
对于想要实现此目的的人,
只需执行以下操作:
IsThreeState=true
IsChecked
到ViewModel 中的bool?
(可为 null bool)属性现在,您可以在 ViewModel 中将其设置为
null
,而用户无法在 View 中执行此操作。for people who want to achieve this
just do this:
IsThreeState=true
IsChecked
to abool?
(nullable bool) property in the ViewModelYou can now set it to
null
in the ViewModel while the user cannot do it in the View.事实上我还有一个更好的。
我发现,如果我为 IsThreeState 创建绑定,然后根据值是否设置来更改值,那么它就可以工作。
现在该复选框将支持三态 IFF,该值在外部设置为 null。
如果该值为 true 或 false,用户将无法将其设置为 null。
Actually I got one better.
I found out that if I create a binding for IsThreeState, then change the value based on whether the value is set or not, then it works.
Now the checkbox will support threestate IFF the value is set to null externally.
If the value is true or false, the user won't be able to set it to null.