zoukankan      html  css  js  c++  java
  • 闲话WinFrom与WPF——一个简单而经典的实现方式

    闲话WinFrom与WPF

    一个简单而经典的实现方式

             如果有这么一个需求。

             一个ComboBox名为cbxProperty中有三项:Text、WindowState、ControlBox 用来控制当前Form窗体对应的三个属性。很显然,Text是字符串,WindowState是枚举(不知道这是枚举的人请翻书),ControlBox则是bool类型。字符串的经典展现方式自然是TextBox,枚举用ComboBox,bool类型的暂时用CheckBox。

             现在改变cbxProperty选择的项,下方用相应的控件展示值,点击OK改变当前窗体属性。

             有一个简单而经典的实现方式。

            

    下方TextBox、ComboBox、CheckBox放在同一位置,初始化先让cbxProperty选中第一条Text对应的设置TextBox显示,其他两个隐藏。

    this.cbxProperty.SelectedIndex = 0;
    
    txtText.Text = this.Text;
    cbxWindowState.Text = this.WindowState.ToString();
    chbxControlBox.Checked = this.ControlBox;

      

    然后对cbxProperty增加SelectedIndexChanged事件处理函数,根据cbxProperty选中的项来控制下方控件的显示状态。

    txtText.Visible = false;
    cbxWindowState.Visible = false;
    chbxControlBox.Visible = false;
    
    switch (cbxProperty.SelectedIndex)
    {
       case 0:
          txtText.Visible = true;
          break;
       case 1:
          cbxWindowState.Visible = true;
          break;
       case 2:
          chbxControlBox.Visible = true;
          break;
       default:
          break;
    }

    最后,点击OK设置当前窗体的三个属性,点击Close关闭窗体。

    this.Text = txtText.Text;
    //this.WindowState = (FormWindowState)Enum.Parse(typeof(FormWindowState), cbxWindowState.Text, true);
    this.WindowState = (FormWindowState)cbxWindowState.SelectedIndex;
    this.ControlBox = chbxControlBox.Checked;

    设置WinDowState时提供了两种方式。

      可以说,在WinForm里要实现这种功能,以上算是一个简单而经典的实现方式。

    但对应而来的问题也会出现,如果将窗体的所有属性都放在cbxProperty中,对每个属性都放对应的控件显而过于麻烦。这时候就有后台生成控件的解决方案。

    界面几乎没有改变,只是下方只是放了一个当做模板用的控件:

    初始化时获得当前窗口的所有属性中类型是string或bool或Enum的,将其以数据源形式赋值给cbxProperty:

    var propData = this.GetType().GetProperties().Where(prop => 
       prop.PropertyType == typeof(string) || prop.PropertyType == typeof(bool) || prop.PropertyType.IsEnum).ToArray();
    cbxProperty.DataSource = propData;
    cbxProperty.DisplayMember = "Name";
    cbxProperty.ValueMember = "PropertyType";

    使用了反射获取属性,筛选使用了linq和lambda表达式(同样,不懂的可以去翻书)。

     1 Control con = null;
     2 PropertyInfo prop = cbxProperty.SelectedItem as PropertyInfo;
     3 
     4 if (prop.PropertyType.IsEnum)
     5 {
     6    ComboBox cbx = new ComboBox();
     7    cbx.DropDownStyle = ComboBoxStyle.DropDownList;
     8    cbx.DataSource = Enum.GetValues(prop.PropertyType);
     9 
    10    cbx.SelectedIndex = -1;
    11    cbx.SelectedIndexChanged += (s, arg) =>
    12       this.GetType().GetProperty(cbxProperty.Text).SetValue(this, cbx.SelectedItem);
    13 
    14    con = cbx;
    15 }
    16 else if (prop.PropertyType == typeof(bool))
    17 {
    18    CheckBox chbx = new CheckBox();
    19    chbx.Text = prop.Name;
    20    chbx.Checked = (bool)prop.GetValue(this);
    21 
    22    chbx.CheckedChanged += (s, arg) =>
    23       this.GetType().GetProperty(cbxProperty.Text).SetValue(this, chbx.Checked);
    24 
    25    con = chbx;
    26 }
    27 else
    28 {
    29    TextBox txt = new TextBox();
    30    txt.TextChanged += (s, arg) =>
    31       this.GetType().GetProperty(cbxProperty.Text).SetValue(this, txt.Text);
    32 
    33    con = txt;
    34 }
    35 
    36 con.Width = _control.Width;
    37 con.Location = _control.Location;
    38 con.Anchor = _control.Anchor;
    39 
    40 this.Controls.Remove(_control);
    41 
    42 _control = con;
    43 this.Controls.Add(_control);

    最后cbxProperty_SelectedIndexChanged稍稍有点复杂。

          其中先判断cbxProperty选择的属性的类型,是枚举则创建ComboBox,是bool则创建CheckBox,其他则创建TextBox(其实也没有其他,只剩字符串),其中对样式、数据和事件进行各自控制,最后统一控制位置、宽度和停靠方式,最后则移除原来的,添加新的。忘了说了,这里设置了一个Control类型的字段,为了获得原来的控件,以便移除等操作。

             由于仅仅是做来实例,其中操作肯定还会有不少错误。也就不一一纠正。

            

             第二种方式除却几个新手可能不懂的反射和lambda表达式,并没有太难的地方,其实和第一种没有本质上的区别,都是通过cbxProperty的SelectedIndexChanged事件去触发,包括改变属性也是通过事件去触发。

            

             然后呢,给个例子三,虽然不符合需求,但我实在在WinForm下没别的办法。只能将就。

            

             当焦点离开的时候,当前窗口对应的属性也会随之变动,与前面不同的是其实现方式。

    txtText.DataBindings.Add("Text", this, "Text");
    chbxControlBox.DataBindings.Add("Checked", this, "ControlBox");
    
    cbxWindowState.DataSource = Enum.GetValues(typeof(FormWindowState));
    cbxWindowState.DataBindings.Add("SelectedItem", this, "WindowState");

    仅有短短几行代码。虽然我也是那种对失去焦点触发比较排斥的那种,但是……

    之所以写下第三种实现方式(严格来说并未实现),是因为我下来要说的与此有关。

    点此下载示例代码

    南琦

    2012-06-16

  • 相关阅读:
    推荐2个Mac OS X上的JSON工具
    20个ios登陆界面
    IOS 真机调试和发布相关证书
    IOS学习路径
    Shell 语法和tips -- 持续更新
    Shell if 参数含义列表
    SimpleCursorAdapter 原理和实例
    Android Service VS AsyncTask VS Thread
    转:Intent 操作常用URI代码示例
    转:Android preference首选项框架
  • 原文地址:https://www.cnblogs.com/nanqi/p/2551880.html
Copyright © 2011-2022 走看看