【问题标题】:TriState Checkbox - how to change the order of the statesTriState Checkbox - 如何更改状态的顺序
【发布时间】:2010-11-23 13:15:24
【问题描述】:

我的应用程序中有一个使用 TriState 模式的 CheckBox。此模式的正常行为似乎在 null、false、true 之间循环。

我想更改此行为,使其在 null、true、false 之间循环。

最好的方法是什么?

我尝试过添加类似这样的点击处理程序:

void cb_Click(object sender, RoutedEventArgs e)
{
    if (((CheckBox)e.Source).IsChecked.HasValue == false)
    {
        ((CheckBox)e.Source).IsChecked = true;
        return;
    }

    if (((CheckBox)e.Source).IsChecked == true)
    {
        ((CheckBox)e.Source).IsChecked = false;
        return;
    }

    if (((CheckBox)e.Source).IsChecked == false)
    {
        ((CheckBox)e.Source).IsChecked = null;
        return;
    }

}

但这似乎完全禁用了复选框。我很确定我遗漏了一些应该很明显的东西。

【问题讨论】:

    标签: wpf checkbox


    【解决方案1】:

    我猜事件处理程序和默认行为只是取消了彼此的效果,所以复选框似乎被禁用了......

    实际上,我最近不得不做同样的事情。我必须继承 CheckBox 并覆盖 OnToggle

    public class MyCheckBox : CheckBox
    {
    
    
        public bool InvertCheckStateOrder
        {
            get { return (bool)GetValue(InvertCheckStateOrderProperty); }
            set { SetValue(InvertCheckStateOrderProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for InvertCheckStateOrder.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InvertCheckStateOrderProperty =
            DependencyProperty.Register("InvertCheckStateOrder", typeof(bool), typeof(MyCheckBox), new UIPropertyMetadata(false));
    
        protected override void OnToggle()
        {
            if (this.InvertCheckStateOrder)
            {
                if (this.IsChecked == true)
                {
                    this.IsChecked = false;
                }
                else if (this.IsChecked == false)
                {
                    this.IsChecked = this.IsThreeState ? null : (bool?)true;
                }
                else
                {
                    this.IsChecked = true;
                }
            }
            else
            {
                base.OnToggle();
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      此处仅出于完整性考虑,另外还有 Windows-Forms 的解决方案。我们必须重写 OnClick 方法,重写 OnStateChanged 会导致显示错误(如果操作不正确,则会导致堆栈溢出)。

      /// <summary>
      /// A <see cref="System.Windows.Forms.CheckBox"/> with the ability to reverse the checkstate order.
      /// </summary>
      /// <seealso cref="System.Windows.Forms.CheckBox" />
      public class CheckBoxReversible : CheckBox
      {
          private bool FInvertCheckStateOrder;
      
          /// <summary>
          /// Gets or sets a value indicating whether to invert the check state order from [Indeterminate->Unchecked->Checked] to [Indeterminate->Checked->Unchecked].
          /// </summary>
          /// <value>
          ///   <c>true</c> to invert the check state order; otherwise, <c>false</c>.
          /// </value>
          public bool InvertCheckStateOrder
          {
              get { return FInvertCheckStateOrder; }
              set { FInvertCheckStateOrder = value; }
          }
      
          /// <summary>
          /// Löst das <see cref="E:System.Windows.Forms.Control.Click" />-Ereignis aus.
          /// </summary>
          /// <param name="e">Eine Instanz der <see cref="T:System.EventArgs" />-Klasse, die die Ereignisdaten enthält.</param>
          protected override void OnClick(EventArgs e)
          {
              if (this.InvertCheckStateOrder)
              {
                  if (this.CheckState == CheckState.Indeterminate)
                      this.CheckState = CheckState.Checked;
                  else
                      if (this.CheckState == CheckState.Checked)
                          this.CheckState = CheckState.Unchecked;
                      else
                          if (this.CheckState == CheckState.Unchecked)
                              this.CheckState = this.ThreeState ? CheckState.Indeterminate : CheckState.Checked;
              }
              else
                  base.OnClick(e);
          }
      }
      

      【讨论】:

        【解决方案3】:

        公认的解决方案是最好的,但如果您不想创建子类,只需执行以下操作:

        void chkbokHeader_Click(object sender, RoutedEventArgs e)
        {
          CheckBox senderChk = sender as CheckBox;
          bool bCheck = false;
          //here, the status is already changed, so rechange:
          if (senderChk.IsChecked == true) // from UNCHECKED
            bCheck = true;
          else if (senderChk.IsChecked == false) //from INDETERMINATE
            bCheck = true;
          else //from CHECKED
            bCheck = false;
        
          senderChk.IsChecked = bCheck;
          e.Handled = true;
        }
        

        它创建(检查)序列:不确定 -> 真 -> 假 -> 真 -> 假 -> 真 -> ...

        【讨论】:

          【解决方案4】:

          非常感谢,用 ToggleButton 解决类似行为非常有用。

          class InvertedToggleButton : ToggleButton
          {
              public bool InvertCheckStateOrder
              {
                  get { return (bool)GetValue(InvertCheckStateOrderProperty); }
                  set { SetValue(InvertCheckStateOrderProperty, value); }
              }
          
              // Using a DependencyProperty as the backing store for InvertCheckStateOrder.  This enables animation, styling, binding, etc...
              public static readonly DependencyProperty InvertCheckStateOrderProperty = DependencyProperty.Register("InvertCheckStateOrder", typeof(bool), typeof(ToggleButtonInvertido), new UIPropertyMetadata(false));
          
              protected override void OnToggle()
              {
                  if (this.InvertCheckStateOrder)
                  {
                      if (this.IsChecked == true)
                      {
                          this.IsChecked = false;
                      }
                      else if (this.IsChecked == false)
                      {
                          this.IsChecked = this.IsThreeState ? null : (bool?)true;
                      }
                      else
                      {
                          this.IsChecked = true;
                      }
                  }
                  else
                  {
                      if (!this.IsChecked.HasValue)
                          this.IsChecked = true;
                      else
                          base.OnToggle();
                  }
              }
          }
          

          【讨论】:

            【解决方案5】:

            正如所指出的,在 WinForms 中没有要覆盖的 CheckBox.OnToggle(),所以在这种情况下,CheckBox.OnClick() 是要去的地方。

            这是 WinForms 复选框的最小实现,它循环 Unchecked -> Indeterminate -> Checked -> Unchecked...,而不是默认的 Unchecked -> Checked -> Indeterminate -> Unchecked...

            using System;
            using System.Windows.Forms;
            
            public class MyCheckBox : CheckBox
            {
                protected override void OnClick(EventArgs e)
                {
                    switch(this.CheckState)
                    {
                        case CheckState.Indeterminate:
                            this.CheckState = CheckState.Checked;
                            break;
                        case CheckState.Checked:
                            this.CheckState = CheckState.Unchecked;
                            break;
                        case CheckState.Unchecked:
                            this.CheckState = this.ThreeState ? CheckState.Indeterminate : CheckState.Checked;
                            break;
                        default:
                            throw new ApplicationException("Unexpected CheckState: " + this.CheckState.ToString());
                    }
                }
            }
            

            或者,如果您很高兴引入对 Windows 分配给 CheckState 的哪些状态的 int 值的依赖,这也可以:

            using System;
            using System.Windows.Forms;
            
            public class MyCheckBox : CheckBox
            {
                protected override void OnClick(EventArgs e)
                {
                    CheckState newState = this.CheckState - 1;
                    if (newState < 0) 
                    {
                        newState = this.ThreeState ? CheckState.Indeterminate : CheckState.Checked;
                    }
                    this.CheckState = newState;
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-08-21
              • 2020-10-07
              • 1970-01-01
              • 2014-07-17
              相关资源
              最近更新 更多