C# WPF取消勾选复选框。

4

我使用的是MS Visual 2013 Express、C#和WPF。

在我的程序中有六个复选框,当其中一个被选中时,其他五个应该取消选中。

我已经谷歌了两个小时,但作为C#初学者找不到解决方案。在Java中,我只需要写checkbox1.setSelected(false);

我在C#代码中添加了一个单击事件、一个选中事件和一个取消选中事件。我在.xaml文件中添加了CheckedUnchecked,但我不知道如何让它工作。

希望你能帮助我 :)

=======================

我的解决方案:

感谢你的帮助。我尝试了一些你建议的“IsChecked”随机东西,幸运地让它工作了。

.Xaml看起来像这样:

            <CheckBox x:Name="CheckBox1" ... Checked="CheckBox1_Checked"  />
            <CheckBox x:Name="CheckBox2" ... Checked="CheckBox2_Checked"  />
            <CheckBox x:Name="CheckBox3" ... Checked="CheckBox3_Checked"  />
            <CheckBox x:Name="CheckBox4" ... Checked="CheckBox4_Checked"  />
            <CheckBox x:Name="CheckBox5" ... Checked="CheckBox5_Checked"  />
            <CheckBox x:Name="CheckBox6" ... Checked="CheckBox6_Checked"  />

CheckBox1的C#代码:

    private void CheckBox1_Checked(object sender, RoutedEventArgs e)
    {
        CheckBox1.IsChecked = true;
        CheckBox2.IsChecked = false;
        CheckBox3.IsChecked = false;
        CheckBox4.IsChecked = false;
        CheckBox5.IsChecked = false;
        CheckBox6.IsChecked = false;
    }

例如对于CheckBox2:
    private void CheckBox2_Checked(object sender, RoutedEventArgs e)
    {
        CheckBox2.IsChecked = true;
        CheckBox1.IsChecked = false;
        CheckBox3.IsChecked = false;
        CheckBox4.IsChecked = false;
        CheckBox5.IsChecked = false;
        CheckBox6.IsChecked = false;
    }

所以最终,这是一个非常容易完成的任务。

8
对我来说,听起来像是“单选按钮”。为什么不使用它呢?您会免费获得这种行为! - BradleyDotNET
@StefanS:为了澄清,这是那种只有一些选项是互斥的情况吗?如果它们全部都是互斥的,那么绝对要使用RadioButton,就像BradleyDotNET建议的那样。但是,如果只有某些选项是互斥的,那么Blam的建议可能是你需要的。 - Troy Gizzi
CheckBox2.IsChecked = false; 看起来很像我的答案。你知道要检查答案。 - paparazzo
5个回答

5
checkbox1.IsChecked = false;

ToggleButton.IsChecked Property

我理解为只有一个特殊的复选框可以取消其他5个的选择。
如果您想同时只选中一个,则可以使用单选按钮(RadioButton)来实现。
默认情况下,无法取消选中单选按钮。
这将允许所有6个都未选中。

我认为使用数据绑定并实现INotifyPropertyChanged更好。

private Bool cbSecial = false;
private Bool cb1 = false;
private Bool cb2 = false;
public Bool CbSpecial 
{
   get { return cbSecial; }
   set 
   {
      if (value == cbSecial) return;
      cbSecial = value;
      if (cbSpecial) 
      {
          Cb1 = false;
          Cb2 = false;
          ... 
      }
      NotifyPropertyChanged("CbSpecial");
   }
}
public Bool Cb1 
{
   get { return cb1; }
   set 
   {
      if (value == cb1) return;
      cb1 = value;
      NotifyPropertyChanged("Cb1 ");
   }
}

这里让人痛苦的部分是你必须对所有其他复选框执行此操作。要获得“RadioButton”行为,您可以使用与https://dev59.com/zXRC5IYBdhLWcg3wJNif中使用的相同绑定过程,并且效果会更好。 - BradleyDotNET
@BradleyDotNET 是的,我对我写的解决方案感到奇怪和肮脏,但我想不出除了 XAML 之外更简单的方法。也许我会使用 DataTriggers 添加一些东西? - furkle
@furkle,您不需要数据触发器;只需将它们全部绑定到相同的值,并使用ValueEqualsConverter即可。对于单选按钮,这种方法非常有效,对于CheckBox也是同样的方式。 - BradleyDotNET
@Blam 是的,但是你怎么知道之前检查过哪个? - furkle
@Blam 我不明白你的观点。当一个被选中时,取消选择其他的。你肯定可以跟踪最后一个并将其取消选择;但这是很多工作,而且你仍然需要迭代以获取选中的值。一个绑定的解决方案会更简单(一旦你完成了基本的MVVM代码)。或者只需使用单选按钮,它应该仍然被绑定。 - BradleyDotNET
显示剩余8条评论

3

BradleyDotNET是正确的 - 在一组中取消任何给定的复选框基本上就是单选按钮的功能,您不需要做任何事情来实现这种行为。

但是,如果您真的想使用复选框,一种实现方式是在ViewModel中保留每个复选框的IsChecked值的引用,这些值已经绑定了TwoWay,还要保留一个内部IEnumerable对象,其中包含六个值,如下所示:

private bool? checkBox1IsChecked = false;
public bool? CheckBox1IsChecked 
{ 
    get { return checkBox1IsChecked;
    set
    {
        UncheckAllCheckBoxes();
        checkBox1IsChecked = true;
    }
}
public bool? CheckBox2IsChecked { get; set; }
...

// include 1 through 6 here
private List<bool?> yourCheckStates = new List<bool> { checkBox1IsChecked, ... };

每当它们之一的状态发生变化时,您可以使用以下类似内容:
private void UncheckAllCheckBoxes()
{
    foreach (bool? cbIsChecked in yourCheckStates)
    {
        cb.IsChecked = false;
    }
}

然后将刚刚更改的复选框的值设置为true。每次勾选一个复选框,其他五个复选框都将被取消勾选。

编辑:如果我误解了这一点,正如Blam所建议的那样,你的意思是特定的一个复选框会取消所有其他复选框的勾选状态,那么只需在该特定复选框的IsChecked属性中包含调用UncheckAllCheckBoxes()的语句,并在所有其他setter中添加一行来将该特殊复选框的IsChecked设置为false。


我不是那样阅读它的。我不把“one”读作“a/any”。"其他5个应该取消选中"。 - paparazzo
@Blam 我已经添加了一个部分来考虑那种可能性。 - furkle

1
你可以采用以下两种方式之一:
  1. 将多个RadioButton放在同一组中
  2. 使用自定义ItemTemplateSelector

单选按钮:
<RadioButton GroupName="MyGrouping" Content="Option 1" IsChecked="True"/>
<RadioButton GroupName="MyGrouping" Content="Option 2" />
<RadioButton GroupName="MyGrouping" Content="Option 3" />

选择器:

<ListBox ItemsSource="{Binding Path=MyOptions}">
  <ListBox.ItemTemplate>
    <DataTemplate>
        <RadioButton Content="{Binding}"
            IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" />
    </DataTemplate>
  </Listbox.ItemTemplate>
</ListBox>

注意:我选择了ListBox作为示例,但您可以选择任何从Selector派生的内容。


你能解释一下你的绑定在那里做了什么吗?我感觉我漏掉了一步。 - furkle
@furkle:具体是哪个绑定? - myermian
啊,我现在明白了 - RadioButton正在查询其所包含的ListBoxItem。花了我一点时间才理解清楚。感谢您的检查。 - furkle

0

你可能会发现这很有用。我有一个“日志级别”wpf菜单,我只想保持1个选择处于活动状态(即,在选择时取消选中所有其他菜单项)。 我的技巧是使用FindName()方法和xaml中的“tag”选项(为漂亮的for循环生成名称)。这样,我避免了一堆“=false”行,每个表单项只需使用一个共享功能调用。

<MenuItem Header="Logging">
  <!-- let's use the cool TAG propery to store the debugLevel code. We don't use it, but the idea is cool -->
  <MenuItem Tag="0" Name="mnuLogging0" Header="None" IsCheckable="True" Checked="mnuLogging_Checked"  />
  <MenuItem Tag="1" Name="mnuLogging1" Header="Normal" IsCheckable="True" Checked="mnuLogging_Checked"  />
  <MenuItem Tag="2" Name="mnuLogging2" Header="Debug Level 1" IsCheckable="True" Checked="mnuLogging_Checked"  />
  <MenuItem Tag="3" Name="mnuLogging3" Header="Debug Level 2" IsCheckable="True" Checked="mnuLogging_Checked"   />
</MenuItem>

取消选中其他选项的函数,以及保存设置的奖励代码是:

private void mnuLogging_Checked(object sender, RoutedEventArgs e) {
  int LogLevel = Convert.ToInt32( ((MenuItem)sender).Tag.ToString());
  Properties.Settings.Default["LogLevel"] = LogLevel.ToString();
  Properties.Settings.Default.Save();
  // Uncheck everybody but me (as determine by "Tag")
  for (int i=0; i < 4; i++) {
    MenuItem item = Main.FindName("mnuLogging"+i) as MenuItem;
    if (i != LogLevel) item.IsChecked = false;
  }
}

0
 {
    if (CheckBox1.Checked)
    {Label1.Text = "Checked Apple"; }
    if (CheckBox1.Checked == false)
    {
        Label1.Text = "Unchecked Apple";
    }

}
protected void CheckBox2_CheckedChanged(object sender, EventArgs e)
{
    if (CheckBox2.Checked)
    { Label1.Text = "Checked Banana"; }
    if (CheckBox2.Checked == false)
    {
        Label1.Text = "Unchecked Banana";
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接