【问题标题】:Is a List<> of variables possible?变量的 List<> 是否可能?
【发布时间】:2011-12-26 19:01:51
【问题描述】:

这可能是一个长镜头,但我正在尝试将我正在处理的程序中的重复次数降至最低,并且遇到了障碍。从下面的 ClearTextBoxes() 方法中可以看出,为了简洁起见,我宁愿将一段非常重复的代码放在 foreach 循环中。 (最初foreach (object box in customBoxes) 循环不存在)。我尝试使用以下列表执行此操作,但无济于事。我不确定这是否是不可能的,或者我只是做错了。如果您能提供任何帮助,我将不胜感激,如果无法做到,那么我该如何缩小此代码块?

谢谢!

List<object> customBoxes = new List<object>();

customBoxes.AddRange(new[] { "TextBox", "DateBox", "DigitBox", "PhoneBox", "WaterTextBox" });



public void ClearTextBoxes()
    {
        ChildControls ccChildren = new ChildControls();

        foreach (object o in ccChildren.GetChildren(rvraDockPanel, 2))
        {
            foreach (object box in customBoxes)
            {
                if (o.GetType() == typeof(TextBox))
                {
                    TextBox txt = (TextBox)o;
                    txt.Text = "";
                }

                if (o.GetType() == typeof(DigitBox))
                {
                    DigitBox digit = (DigitBox)o;
                    digit.Text = "";
                }

                if (o.GetType() == typeof(PhoneBox))
                {
                    PhoneBox phone = (PhoneBox)o;
                    phone.Text = "";
                }

                if (o.GetType() == typeof(DateBox))
                {
                    DateBox date = (DateBox)o;
                    date.Text = "";
                }

                if (o.GetType() == typeof(WatermarkTextBox))
                {
                    WatermarkTextBox water = (WatermarkTextBox)o;
                    water.Text = "";
                }
            }
        }
    }

【问题讨论】:

  • 我会从每个控件继承并应用一个带有 ClearText() 方法的接口。
  • 第二个循环的作用是什么(foreach(customBoxes 中的对象框))?
  • 你可以看看这个问题:stackoverflow.com/questions/619767/…
  • @James:将其添加为答案。
  • @jgauffin 我已经添加了,谢谢。

标签: c# list variables object foreach


【解决方案1】:

作为对到目前为止的几个答复的回应,这是我为自定义框准备的类文件。 NumberTextBox 类是 VS 添加的默认 sn-p。我没用过,也没有删。除了 DateBox(为了节省空间而折叠起来)类之外,还有一个 PhoneBox 类也继承自 DigitBox。 DigitBox 继承的 WatermarkTextBox 类位于 WpfToolkit.Extended.dll 中。这些类中唯一真正的区别是每个类都添加了一个方法来允许/禁止按下格式化键(括号、句点、连字符等)。

这个类基本上是由于尝试合并我在网上找到的几个不同的 sn-ps 的结果,但是这些框的目的是启用水印并限制可以输入这些框的字符。

public class NumberTextBox : Control
{
    static NumberTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NumberTextBox), new FrameworkPropertyMetadata(typeof(NumberTextBox)));
    }

}    

public class DigitBox : WatermarkTextBox, IClearable
{
    #region Constructors
    ///<summary>
    ///The default constructor
    /// </summary>
    public DigitBox()
    {
        TextChanged += new TextChangedEventHandler(OnTextChanged);
        KeyDown += new KeyEventHandler(OnKeyDown);
        PreviewKeyDown += new KeyEventHandler(OnPreviewDown);
    }
    #endregion

    #region Properties
    new public String Text
    {
        get { return base.Text; }
        set
        {
            base.Text = LeaveOnlyNumbers(value);
        }
    }
    #endregion

    #region Functions
    public bool IsNumberKey(Key inKey)
    {
        if (inKey < Key.D0 || inKey > Key.D9)
        {
            if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
            {
                return false;
            }
        }
        return true;
    }

    public bool IsActionKey(Key inKey)
    {
        return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return;
    }

    public string LeaveOnlyNumbers(String inString)
    {
        String tmp = inString;
        foreach (char c in inString.ToCharArray())
        {
            if (!IsDigit(c))
            {
                tmp = tmp.Replace(c.ToString(), "");
            }
        }
        return tmp;
    }

    public bool IsSpaceKey(Key inKey)
    {
        if (inKey == Key.Space)
        {
            return true;
        }
        return false;
    }

    public bool IsDigit(char c)
    {
        return (c >= '0' || c <='9');
    }
    #endregion

    #region Event Functions
    protected virtual void OnKeyDown(object sender, KeyEventArgs e)
    {
        e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsSpaceKey(e.Key);
    }

    protected virtual void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        base.Text = LeaveOnlyNumbers(Text);
    }

    protected virtual void OnPreviewDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Space)
        {
            e.Handled = true;
        }
    }
    #endregion
}


public class DateBox : DigitBox

【讨论】:

    【解决方案2】:

    所有的输入框不都是Control对象的一部分吗?

    如果是这样,并且您想清除控件中的所有文本 那么我可能会有这样的方法:

    public void ClearText(List<Control> items)
        {
            foreach (Control control in items)
            {
                control.Text = string.Empty;
            }
        }
    

    如果您只想定位特定类型的控件

    public void ClearText(List<Control> items)
            {
                foreach (Control control in items)
                {
                    if (control is TextBox)
                        ((TextBox)control).Text = string.Empty;
                    else if (control is DigitBox)
                        ((DigitBox)control).Text = string.Empty;
                    else
                    { // Handle anything else.}
                }
            }
    

    【讨论】:

      【解决方案3】:

      我会用ClearText() 方法创建一个interface

      interface IClearable
      {
        public void ClearText();
      }
      

      然后您可以从每个控件继承并应用该接口:

      class ClearableDigitBox : DigitBox, IClearable
      {
        public void ClearText() {
          Text = String.Empty;
        }
      }
      // etc...
      

      所以它只是:

      var list = new List<IClearable>;
      // ...
      foreach (IClearable control in list) control.ClearText();
      

      【讨论】:

      • 我试过了,并且用这种方法最接近成功,但我认为问题是我只是不知道如何填充该列表,就像添加它们的语法一样.
      • @KevenM 你试过foreach (object o in ccChildren.GetChildren(rvraDockPanel, 2)) list.Add(o as MyClearable);你还需要确保该停靠面板中的所有控件都是你创建的后代类型,即ClearableDigitBox
      • 是的,也无法让它工作。但是在尝试的过程中,我有一个想法,也许您可​​以验证这是否可行(不完全确定如何实现它)。正如我在第二篇文章中指出的那样,digitbox、phonebox 和 datebox 之间的唯一区别是 IsFormattingKey 方法的存在。我可以为那些使用接口,而不是将它们写为继承的类吗?因为那时 foreach 循环可能引用一种自定义框而不是 5,对吧?
      • 如果它们都继承自 WatermarkTextbox 那么您不需要接口,只需将每个对象转换为 WatermarkTextbox 并将其 Text 属性设置为空。
      【解决方案4】:

      您可以以某种方式使用反射来模仿某些管道化行为,但我不会采用该解决方案,因为它不高效且丑陋。

              foreach (object box in customBoxes) 
              { 
                  var boxType = box.GetType();
                  var textProperty = boxType.GetProperty("Text");
                  if (textProperty != null && textProperty.CanWrite)
                  {
                      textProperty.SetValue(box, "", null);
                  }
              }
      

      或者你可以使用动态来达到同样的效果:

            foreach (dynamic box in customBoxes)
            {
                 box.Text = "";
            }
      

      要走的路是让您的自定义控件实现单个接口 IWithTextProperty,它当然会公开文本属性。

      【讨论】:

      • 反射是我在最近几天搜索帖子之前从未听说过的东西。 :) 这绝对是我需要研究的东西……与动态相同。而且我对界面感到不安。你知道任何非常基本的界面指南吗?
      【解决方案5】:
      List<Type> customBoxes = new List<Type>();
      
      customBoxes.AddRange(new[] { typeof(PhoneBox), typeof(DigitBox), ....." });
      
      foreach (Control c in this.Controls)
      {
        if (customBoxes.Contains(c.GetType()))
        {
          c.Text = string.Empty;
        }
      }
      

      【讨论】:

      • 您应该提到,这使得所有customBoxes 继承Control 的(可能是正确的)假设......但OP 对此并不清楚。
      • 对不起,如果我不清楚,但实际上他们没有继承 Control(至少我不认为他们这样做)。它们继承自 ExtendedToolkit dll 中的 WatermarkTextBox。当我尝试这种方法时,.Controls 部分给出了一个错误,指出没有名为控件的定义或扩展方法。
      猜你喜欢
      • 2016-07-01
      • 1970-01-01
      • 2017-02-18
      • 1970-01-01
      • 2022-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多