本文介绍了指导重复复合控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 一直在尝试开发一个复合复选框控件,它基本上复制了Excel自动过滤器下拉列表的工作方式(只是UI的行为,而不是过滤部分)。因此可以将其视为单级TreeView,其中父级标记为(全选)并具有三态复选框(未选中,已选中,已混合)。下面的孩子会有正常的复选框,无论是选中还是未选中。 唯一的另一个问题是孩子会/可能有多列 - 取决于数据是什么加载(而Excel下拉式自动过滤器只有一列 - 唯一值)。 这个想法是让它成为可以(重新)在任何地方使用的通用控件。并且,如果我能够让它工作(!),我会在这里发布。 我对这种类型的开发相当新,但是我我一直在尝试使用带有两个ListView控件的ContainerControl(两者都将其View属性设置为Details)。第一个(标题)ListView只有一个项目 - 它的文本设置为(全选)。第二个(正文)ListView将有多个列和行,具体取决于加载的数据。他们会像Excel自动过滤器一样互相交流。 无论如何,假设任何人还在读这篇文章(!),我的问题是我在正确的轨道给出了我正在尝试做的事情,还是有更好的方法?解决方案 这是真正的问题,这是特别值得回答;并且回答它可以真正帮助你。 我认为你只需要一个想法如何将一些子控件的事件委托给父控件,以便处理它们的方式您的控件的用户,不会暴露孩子自己(这可能会,但当然会违反正确的封装)。 这个想法很简单,就在只有一个事件的例子: 使用系统; 使用 System.Collections.Generic; 使用 System.Windows.Forms; public class CheckBoxCollectionEventArgs:System.EventArgs { internal CheckBoxCollectionEventArgs( int index,CheckBox checkBox){ 这 .checkBoxIndex = index; this .checkBox = checkBox; } // CheckBoxCollectionEventArgs public int checkBoxIndex { get ; 内部 设置; } public CheckBox checkBox { get ; 内部 设置; } } // class CheckBoxCollectionEventArgs public class MyCompositeCheckBox / * ... * / { List< CheckBox> checkBoxes = new List< CheckBox>(); // 例如 // ... public MyCompositeCheckBox(){ // ... for ( int index = 0 ; index < checkBoxes.Count; ++ index){ // not foreach, // 因为索引用于调用 CheckBox checkBox = checkBoxes [index]; checkBox.CheckStateChanged + =(sender,eventArgs)= > { if (CheckBoxCollectionCheckedStateChanged!= null ) CheckBoxCollectionCheckedStateChanged.Invoke( this , new CheckBoxCollectionEventArgs(index,checkBox)); }; // checkBox.CheckStateChanged } // loop } // MyCompositeCheckBox public System.EventHandler< CheckBoxCollectionEventArgs> CheckBoxCollectionCheckedStateChanged; } // class MyCompositeCheckBox 当你表达了对lambda的一些担忧时,这里是没有lambda语法的匿名方法: // ... checkBox.CheckStateChanged + = 委托( 对象发​​件人, CheckBoxCollectionEventArgs eventArgs){ if (CheckBoxCollectionCheckedStateChanged!= null ) CheckBoxCollectionCheckedStateChanged.Invoke( this , new CheckBoxCollectionEventArgs(index,checkBox)); }; // checkBox.CheckStateChanged // ... 即使使用.NET Framework 2.0,也可以使用此类语法(我不认为任何早期版本可以被认真考虑,但2.0是一个不错的版本,当引入泛型,以及匿名方法和其他重要的东西)。 但是,在这个非常应用的目的中,你不必了解lambda的所有功能和理论,这是一个完整的软件基础领域。对于这个例子,它恰好足以正式理解语法,以及类型推断的简单情况。所以,这里没有很多lambda,我主要是为了能够享受类型推断:正如你所看到的,我没有输入 sender 的类型和 eventArgs 参数。为什么?它们是真实的类型,与上面显示的无lambda版本的代码完全相同,只有类型推断来自哪里?从'+ ='左侧的事件声明,即 System.EventHandler< CheckBoxCollectionEventArgs> 。 也许,理解闭包更为重要,这是许多语言中的一个非常基本的特征,也是现代(而不是那么现代)语言和系统中的基本现象。这是您可以将这些本地(堆栈)变量传递给处理程序的方式,以允许用户知道索引和调用原始事件的复选框的实例。请参阅: http://en.wikipedia.org/wiki/Closure_(computer_science) [ ^ ]。 [结束编辑] 你明白了吗?您在应用程序中预先创建了一些事件处理程序(显示为​​单个匿名方法,索引使用 closure 传递并使用客户提供的事件处理程序的调用来实现它,不要忘记将其检查为null。 -SA Have been trying to develop a composite check box control that essentially replicates how an Excel autofilter dropdown works (just the behavior of the UI, not the filtering part). So it could be thought of as a single level TreeView, where the parent is labeled "(Select All)" and has a tri-state checkbox (unchecked, checked, mixed). The children beneath would have normal checkboxes, either checked or unchecked.The only other wrinkle is that the children would/could have multiple columns - depending on what data has been loaded (whereas an Excel dropdown autofilter has just one column - the unique values).The idea was to make it a generic control that could be (re)used anywhere. And, if I could ever get it to work(!), that I'd post here.I'm fairly new to this type of development, but I've been trying to use a ContainerControl with two ListView controls inside (both with their View property set to "Details"). The first (header) ListView has just one item - with it's text set to "(Select All)". The second (body) ListView would have multiple columns and rows depending on what data is loaded. And they would interact with each other the way an Excel autofilter behaves.Anyway, assuming anybody is still reading this far(!), my question is am I on the right track given what I'm trying to do, or is there a better approach? 解决方案 This is really the question, which is specific enough to worth answering; and answering it can really help you.I think you simply need an idea how to delegate events of some child controls to a parent control the way they can be handled by the users of your controls, without exposing the children themselves (which would be possible but of course would violate proper encapsulation).The idea is simple enough, just on the example of only one event:using System;using System.Collections.Generic;using System.Windows.Forms;public class CheckBoxCollectionEventArgs : System.EventArgs { internal CheckBoxCollectionEventArgs(int index, CheckBox checkBox) { this.checkBoxIndex = index; this.checkBox = checkBox; } // CheckBoxCollectionEventArgs public int checkBoxIndex { get; internal set; } public CheckBox checkBox { get; internal set; }} // class CheckBoxCollectionEventArgspublic class MyCompositeCheckBox /* ... */ { List<CheckBox> checkBoxes = new List<CheckBox>(); // for example // ... public MyCompositeCheckBox() { // ... for(int index = 0; index < checkBoxes.Count; ++index) { // not foreach, // because index is used in invocation CheckBox checkBox = checkBoxes[index]; checkBox.CheckStateChanged += (sender, eventArgs) => { if (CheckBoxCollectionCheckedStateChanged != null) CheckBoxCollectionCheckedStateChanged.Invoke( this, new CheckBoxCollectionEventArgs(index, checkBox)); }; //checkBox.CheckStateChanged } // loop } // MyCompositeCheckBox public System.EventHandler<CheckBoxCollectionEventArgs> CheckBoxCollectionCheckedStateChanged;} // class MyCompositeCheckBox[EDIT]As you expressed some concerns about lambda, here is the anonymous method without lambda syntax://... checkBox.CheckStateChanged += delegate( object sender, CheckBoxCollectionEventArgs eventArgs) { if (CheckBoxCollectionCheckedStateChanged != null) CheckBoxCollectionCheckedStateChanged.Invoke( this, new CheckBoxCollectionEventArgs(index, checkBox)); }; //checkBox.CheckStateChanged//...You can use such syntax even with .NET Framework 2.0 (I don't think any earlier version could be considered seriously, but 2.0 is a decent version, when generics were introduced, as well as anonymous methods and other important stuff).However, in this very application purpose, you don't have to understand all the power and theory of lambda, which is a whole big fundamental field of software. For this example, it's just enough to understand the syntax formally, as well as the simple case of type inference. So, there is no much of lambda here, I used it mostly to be able to enjoy type inference: as you can see, I did not have to enter the types for sender and eventArgs parameters. Why? They are real types, exactly the same as in lambda-free version of code shown above, only the types are inferred from — where? From the declaration of the event on the left side of '+=', that is, System.EventHandler<CheckBoxCollectionEventArgs>.Maybe, it's more important to understand closures, which is a very fundamental feature in many language, and the very fundamental phenomenon in modern (and not so modern) languages and systems. This is how you can pass those local (stack) variables to the handler, to allow the user to know the index and the instance of the check box which invoked the original event. Please see:http://en.wikipedia.org/wiki/Closure_(computer_science)[^].[END EDIT]Are you getting the idea? You pre-create some event handlers in your application (shown as one single anonymous method, index is passed using closure) and implement it using the invocation of customer-supplied event handler, not forgetting about checking it for null.—SA 这篇关于指导重复复合控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-30 02:15