none
召集讨论 DataGridViewComboBoxColumn 可编辑/输入版本 RRS feed

  • 问题

  • 需求:DataGridViewComboBoxColumn 可编辑/输入版本。
    实现方法:将EditingControl改成ComboBox,再输入完成和验证完成之间检查Items,如果不存在该值则插入。
    本人目前搜集到的版本有两个。

    1.GetFormattedValue版本:http://blog.csdn.net/maji9370/archive/2009/09/16/4557770.aspx
    2.OnEditingControlShowing版本:http://www.cnblogs.com/michaelhuwei/archive/2008/09/28/1301290.html

    就本人使用体验,
    GetFormattedValue版本 将造成每次频繁触发GetFormattedValue事件(鼠标滑过该列、窗口重绘、单元格赋值等),如果在插入Items前还要处理(验证/修正)值则将明显造成显示刷新延迟,因为触发常常是整列每个单元格多次触发。
    OnEditingControlShowing版本没有显示刷新延迟,因为只有在需要验证时才处理Items插入事件,缺点是每次进入编辑都要重载DorDownStyle,如果该Items.Count太大则进入编辑将有明显延迟(我的是123,延迟600毫秒左右)。

    论题:
    看过VC(MFC)的类似实现并没有明显延迟,请试论C#是否能实现?
    • 已移动 Sheng Jiang 蒋晟Moderator 2010年5月12日 19:06 System.Windows.Forms (发件人:Visual C#)
    • 已更改类型 Jo Sader 2010年5月13日 11:22 没有人关注啊~
    2010年5月12日 12:48

答案

  • 你好,

     

    如果你需要可编辑的datagridviewcomboboxcolumn, 你可以参考一下一下faq.

    26.如何让DataGridViewComboBoxCell可以编辑?

    原英文版本:

    26. How do I enable typing in the combo box cell?

     

    原理:

    editingControlShowing 事件里面, 抓出 showing control – combobox 设置combobox dropdownstyle dropdown 这样就可以输入了。

    但是由于 comboboxcolumn 需要 所有comboboxcell的值 都在 comboboxcolumn dropdownlist 里面,否则会抛出 dataerror

    为了让其通过 validation,我们需要把输入的不存在的值 加到dropdownlist 里面 (如果是绑定的话, 可以手动改datasource)。

     

    Best regards,

    Ling Wang


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • 已标记为答案 Jo Sader 2010年5月29日 2:43
    2010年5月14日 3:25
    版主

全部回复

  • private void dataGridView1_EditingControlShowing(object sender,
     DataGridViewEditingControlShowingEventArgs e)
    {
     ComboBox combo = e.Control as ComboBox;
     if (combo != null)
     {
     combo.SelectedIndexChanged +=
     new EventHandler(ComboBox_SelectedIndexChanged);
     }
    }
    private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
     ComboBox cb=(ComboBox)sender;
    }
    

     

    以上是MSDN里的例子,效果不对。

    貌似 SelectIndexChanged 比 EditingControlShowing早触发,实际运行效果是从一个TextBox列改选到ComboBox列不触发SelectIndexChanged ,要在ComboBox里切换单元格才会有效果。
    我换用了Enter事件,结果每次进入(鼠标单击或设置为CurrentCell)都会触发两次,有延迟。

    经过多次断点测试分析发现:combo.DropDownStyle = ComboBoxStyle.DropDown; //此处将重新触发Enter,在此之前需清除事件绑定。
    目前延时100ms

    我的机器配置:E2180(双核 2.00GHz) 2.0GB内存 NVIDIA 8600GT 显卡

    EventHandler eventHandler;
        private void ChannelDgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
    
            ComboBox combo = e.Control as ComboBox;
            if (combo != null)
            {
              if (eventHandler == null)
              {
                eventHandler = new EventHandler(combo_Enter);
                //eventHandler = new EventHandler(combo_SelectedIndexChanged);
              }
              //combo.SelectedIndexChanged += eventHandler;
              combo.Enter -= eventHandler;  //取消可能的事件绑定
              combo.Enter += eventHandler; //绑定事件
            }
        }
        void combo_Enter(object sender, EventArgs e)
        {
          DateTime st = DateTime.Now;
    
          ComboBox combo = sender as ComboBox;
          if (combo != null)
          {
            combo.Enter -= eventHandler;  //取消事件绑定
             combo.DropDownStyle = ComboBoxStyle.DropDown; //此处将重新触发Enter
            //cb.AutoCompleteMode = AutoCompleteMode.Suggest;
            combo.MaxLength = 5;
          }
          labTimeSpan.Text = (DateTime.Now - st).ToString();
        }
    
    

     

    我最新的猜测是EditingControlShowing之前要生成EditingControl,这里调用的是DataGridViewComboBoxEditingControl,DropDownStyle 被初始化成DropList,我再改回DropDown等于是改变了两次所以才会有那么大延迟,不知对否

     

    2010年5月12日 12:54
  • 补充Items.Count较小的时候延迟可以接受,我的是200+,延迟基本在100ms以上,可以看出来了。

    据说白天人比较多,顶起求解。

     

    2010年5月13日 0:04
  • 白天真是漫长啊
    2010年5月13日 2:39
  • 已经证实DataGridViewComboBoxCell 的 InitializeEditingControl方法里有

    editingControl.DropDownStyle = ComboBoxStyle.DropDownList;

    这一句,亦即如果仅仅是扩展,调用base.InitializeEditingControl()就必然会将DropDownStyle 改成 DropDownList,我需要的是DropDown类型的可输入类型,如此反复花费双倍时间代价。求高手给个可用解决方案,反编译出来 DataGridViewComboBox 源码编译不了,网上的都是基于base.InitializeEditingControl()的,Items少的时候没感觉,多了影响就大了。

    2010年5月13日 11:42
  • 你好,

     

    如果你需要可编辑的datagridviewcomboboxcolumn, 你可以参考一下一下faq.

    26.如何让DataGridViewComboBoxCell可以编辑?

    原英文版本:

    26. How do I enable typing in the combo box cell?

     

    原理:

    editingControlShowing 事件里面, 抓出 showing control – combobox 设置combobox dropdownstyle dropdown 这样就可以输入了。

    但是由于 comboboxcolumn 需要 所有comboboxcell的值 都在 comboboxcolumn dropdownlist 里面,否则会抛出 dataerror

    为了让其通过 validation,我们需要把输入的不存在的值 加到dropdownlist 里面 (如果是绑定的话, 可以手动改datasource)。

     

    Best regards,

    Ling Wang


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • 已标记为答案 Jo Sader 2010年5月29日 2:43
    2010年5月14日 3:25
    版主
  • 你好,

     

    如果你需要可编辑的datagridviewcomboboxcolumn, 你可以参考一下一下faq.

    26.如何让DataGridViewComboBoxCell可以编辑?

    原英文版本:

    26. How do I enable typing in the combo box cell?

     

    原理:

    editingControlShowing 事件里面, 抓出 showing control – combobox 设置combobox dropdownstyle dropdown 这样就可以输入了。

    但是由于 comboboxcolumn 需要 所有comboboxcell的值 都在 comboboxcolumn dropdownlist 里面,否则会抛出 dataerror

    为了让其通过 validation,我们需要把输入的不存在的值 加到dropdownlist 里面 (如果是绑定的话, 可以手动改datasource)。

     

    Best regards,

    Ling Wang


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.


    先生/女士:

    回帖前请先看帖,然后再看看您的回复是否有意义?

    2010年5月14日 6:11
  • private void dataGridView1_EditingControlShowing(object sender,
    
     DataGridViewEditingControlShowingEventArgs e)
    
    {
    
     ComboBox combo = e.Control as ComboBox;
    
     if (combo != null)
    
     {
    
     combo.SelectedIndexChanged +=
    
     new EventHandler(ComboBox_SelectedIndexChanged);
    
     }
    
    }
    
    private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
    
    {
    
     ComboBox cb=(ComboBox)sender;
    
    }
    
    
    
    

     

    以上是MSDN里的例子,效果不对。

    貌似 SelectIndexChanged 比 EditingControlShowing早触发,实际运行效果是从一个TextBox列改选到ComboBox列不触发SelectIndexChanged ,要在ComboBox里切换单元格才会有效果。
    我换用了Enter事件,结果每次进入(鼠标单击或设置为CurrentCell)都会触发两次,有延迟。

    经过多次断点测试分析发现:combo.DropDownStyle = ComboBoxStyle.DropDown; //此处将重新触发Enter,在此之前需清除事件绑定。
    目前延时100ms

    我的机器配置:E2180(双核 2.00GHz) 2.0GB内存 NVIDIA 8600GT 显卡

    EventHandler eventHandler;
    
      private void ChannelDgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    
      {
    
    
    
        ComboBox combo = e.Control as ComboBox;
    
        if (combo != null)
    
        {
    
         if (eventHandler == null)
    
         {
    
          eventHandler = new EventHandler(combo_Enter);
    
          //eventHandler = new EventHandler(combo_SelectedIndexChanged);
    
         }
    
         //combo.SelectedIndexChanged += eventHandler;
    
         combo.Enter -= eventHandler; //取消可能的事件绑定
    
         combo.Enter += eventHandler; //绑定事件
    
        }
    
      }
    
      void combo_Enter(object sender, EventArgs e)
    
      {
    
       DateTime st = DateTime.Now;
    
    
    
       ComboBox combo = sender as ComboBox;
    
       if (combo != null)
    
       {
    
        combo.Enter -= eventHandler; //取消事件绑定
    
         combo.DropDownStyle = ComboBoxStyle.DropDown; //此处将重新触发Enter
    
        //cb.AutoCompleteMode = AutoCompleteMode.Suggest;
    
        combo.MaxLength = 5;
    
       }
    
       labTimeSpan.Text = (DateTime.Now - st).ToString();
    
      }
    
    
    
    
    
    

     

    我最新的猜测是EditingControlShowing之前要生成EditingControl,这里调用的是DataGridViewComboBoxEditingControl,DropDownStyle 被初始化成DropList,我再改回DropDown等于是改变了两次所以才会有那么大延迟,不知对否

     


    你好 我主要從事.NET B/S方面的開發,對WinForm中最複雜的DataGridView沒有仔細的研究過,不過對於你這裡提到的猜想,可以添加對DropDownStyle監視,然後在各個方法中斷點查看它的值 是否是你所猜想的那樣就可以確定了。
    I see you~http://hi.baidu.com/1987raymondMy Blog~~~
    2010年5月14日 7:44
    版主
  • 已经证实DataGridViewComboBoxCell 的 InitializeEditingControl方法里有

    editingControl.DropDownStyle = ComboBoxStyle.DropDownList;
    

    这一句,亦即如果仅仅是扩展,调用base.InitializeEditingControl()就必然会将DropDownStyle 改成 DropDownList,我需要的是DropDown类型的可输入类型,如此反复花费双倍时间代价。求高手给个可用解决方案,反编译出来 DataGridViewComboBox 源码编译不了,网上的都是基于base.InitializeEditingControl()的,Items少的时候没感觉,多了影响就大了。

     

    目前关注如何解决延迟。

    2010年5月15日 1:41
  • 女士们、先生们:

        我坚持,有意义的回复只有两种,一种是纯粹的帮顶,一种是积极回答。复制黏贴无意义的链接肯定不属于这两种,除非发问者连搜索资料都没做就盲目的发问了,这样的人,需要事无巨细的帮助,给他个MSDN首页链接会更好些。

        欢迎帮顶、指教,谢绝黏贴。

    2010年5月26日 14:34
  • 我提个方案,你看可行不.

    自定义一个DataGridViewColumn ,这个Column就直接放置一个ComboBox,这个ComboBox本身就可编辑的.

    其原理就好比在一个窗体上直接放置一个ComboBox,就不用通过什么OnEditingControlShowing之类的方法在

    ComboBox和EditTextBox之间切换.

    当然,如果你想要在Column没有在编辑状态下时,不显示下拉符号,你可以自绘ComboBox本身,在ComboBox没有

    输入焦点时,不绘制下拉符号.

    2010年5月27日 1:44
  •  

    如果我们没有看你的贴,怎么会 花时间 给你粘相关的链接还加上自己的描述呢?大家都是很热心想帮你。

     

    如果你觉得我们的回复有哪些地方不正确的话,你可以指明哪里不能实现你的需求,哪里误解了你,别人给你的回复中有哪些地方实现起来有问题,你可以再声明一下你想实现的是哪种,以免下次有人看到的帖子会有同样的误解。如果你只是说 别人没有看你的贴,别人再回过头来看一遍你的帖子后, 可能还是和以前一样的想法。

     

    你的回复中,看到你已经做了很多的尝试,你发现或多或少的有些缺陷,所以我才给出了另外一种解决方案,这个解决方案和你所提供的思路是差不多的,只是处理上有点不同。

     

    你的需求是 需求:DataGridViewComboBoxColumn 可编辑/输入版本。 ,我给你提供那一个解决方案也可以做到这一点。你可以尝试一下。

     


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    2010年5月27日 2:29
    版主
  •  

    如果我们没有看你的贴,怎么会 花时间 给你粘相关的链接还加上自己的描述呢?大家都是很热心想帮你。

     

    如果你觉得我们的回复有哪些地方不正确的话,你可以指明哪里不能实现你的需求,哪里误解了你,别人给你的回复中有哪些地方实现起来有问题,你可以再声明一下你想实现的是哪种,以免下次有人看到的帖子会有同样的误解。如果你只是说 别人没有看你的贴,别人再回过头来看一遍你的帖子后, 可能还是和以前一样的想法。

     

    你的回复中,看到你已经做了很多的尝试,你发现或多或少的有些缺陷,所以我才给出了另外一种解决方案,这个解决方案和你所提供的思路是差不多的,只是处理上有点不同。

     

    你的需求是 需求:DataGridViewComboBoxColumn 可编辑/输入版本。 ,我给你提供那一个解决方案也可以做到这一点。你可以尝试一下。

     


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.


    对不起,必须承认我的表述有问题。

    提出此帖仅为了探求一种无延迟的实现方式,网上可以找见实现方式在Items过大时表现出了明显的延迟,因而有此一问。

    2010年5月27日 6:17