C # Winform uses FlowLayoutPanel and custom editing controls to quickly build an editing form page for C/S,
In my personal understanding, the purpose of developing an application, whether B/S or C/S structure type, is nothing more than implementation for usersQuery, add, modify, delete,Queries are used most often, and the development and design scenarios are also the most complex, including but not limited to: Table Record query, REPORT query, export file query, and so on, followed by adding, changing, and deleting, I am collectively referred to as editing here, and editing is more common in development and design scenarios. Most of them use editing components (text box, drop-down box, selection box, and number box) because the development and design scenarios of queries need to be carried out with the actual data and customer requirements, we will not discuss them here, this article mainly describes how to use FlowLayoutPanel and custom editing controls of my (dream trip) to quickly build a C/S version of the editing form page.
I have experienced ASP development. net mvc website users know that when building an editing page, we can quickly generate corresponding editing controls through HtmlHelper extension class methods, such as Html. labelFor, Html. textBoxFor and so on, but there is no similar method in the Winform project that allows us to quickly build and edit the form page, so to reduce the time consumption that we often encounter, without any technical development workload, I developed a series of similar editing controls, including: CTextBox [text box], CPictureBox [Image Box], CNumberBox [number Box], CDropDownBox [drop-down box], CDisplayBox [display box], CCheckBox [check box ], these controls have some common features, such as: Label: Display and edit project name, Value: control Value, ValueFor <TEntity>: Quick Setting of control-related attributes, these common features are the key to quickly constructing and editing controls. Of course, each editing control has its own unique attributes. For example, CTextBox can be used to set whether to display buttons, whether to read-only, and whether to have multiple rows. CNumberBox can be used to set decimal places, maximum values, and minimum values. Because these controls may add up many codes, here we only use CTextBox as an example to analyze and describe it. CTextBox is the control with the most attributes.
First, let's take a look at the interface design of the CTextBox control, such:
It can be seen that the CTextBox control is composed of a TableLayouPanel, a Label, A TextBox, and a Button:
TableLayouPanel is the top-level container of the Control. Its DOCK attribute is set to Fill to occupy the entire control. There is also a row and three columns, and the width of the first column is set to automatic adjustment, the width of the second column is set to 100%, and the width of the third column is set to automatic adjustment, for example:
TableLayouPanel is designed to automatically adjust the width of the first column according to the LABEL content, set the width of the second column to the width of the TextBox, and set the width of the third column to the width of the Button, we change the entire CTextBox size to ensure layout consistency (that is, within the total width of CTextBox, the TextBox width is the total width of CTextBox-the actual width of the LABEL and Button)
The Label control is used as the display and editing project name. Its property AutoSize is set to True, and Anchor is set to Left. Purpose: To center Left in the first column, and the width varies according to the actual content.
The TextBox Control is used as the content for editing. Its attribute is set Anchor to Top, Bottom, Left, Right. purpose: to occupy the second column of the TextBox Control, that is, if the width and height of the control change, the TextBox Control also changes. This is very important!
The Button control is an optional part. If you want to use the control value from other options (such as browsing files and saving files), you can set its CTextBox. the DispalyOpenButton can be set to True. Similarly, the Anchor attribute of the DispalyOpenButton is set to Left and the fixed width and height are adjusted. The purpose is to center Left in the third column and the width remains unchanged.
Shows the overall effect:
I used the red line here. Do you see the result? That is, I drag and drop three CTextBox controls and set the LABEL content to different. Unless the width of the control is changed manually, the width of each control is the same, in this way, the FlowLayoutPanel control is combined with the stream layout (that is, each control is arranged in order. If the width and height change, the control is arranged in order ), you can quickly build an editing page to see the effect that will eventually be used in my project. Do you think it is good:
This is the layout before changing the width. There are five columns. I have marked them with red boxes and they are all aligned.
This is my layout after narrowing down the width. There are two columns. I have marked them with red boxes and they are still aligned.
You do not need to write any code for the above layout. The Code only sets the corresponding attributes and methods, as shown below:
Source code of the CTextBox control:
Using System; using System. collections. generic; using System. componentModel; using System. drawing; using System. data; using System. linq; using System. text; using System. windows. forms; using System. linq. expressions; using Zwj. TEMS. common; namespace TEMS. controls {public partial class CTextBox: UserControl, IZwjDefControl {[Description ("this event is triggered when the button is clicked")] public event EventHandler OnOpen; public CTextBox () {Init IalizeComponent (); this. dispalyOpenButton = false;} [Browsable (true)] [Description ("set text box Value")] public string value {get {return textBox1.Text;} set {textBox1.Text = Value ;}} [Browsable (true)] [Description ("set Label value")] public string Label {get {return label1.Text;} set {label1.Text = value ;}} [Browsable (true)] [Description ("enable or disable setting")] public bool DispalyOpenButton {get {return butto N1.Visible;} set {button1.Visible = value; textBox1.ReadOnly = button1.Visible;} [Browsable (true)] [Description ("set whether multiple rows are allowed")] public bool AllowMultiline {get {return textBox1.Multiline;} set {textBox1.Multiline = value; if (textBox1.Multiline) {textBox1.ScrollBars = ScrollBars. vertical ;}} public void ValueFor <TEntity> (Expression <Func <TEntity, dynamic> selectField, string fieldValue, Bool displayBtn = false, bool allowMultiline = false) where TEntity: class {var fieldInfo = General. getPropertyInfo (selectField); this. label = General. getDisplayName (fieldInfo); this. value = fieldValue; this. dispalyOpenButton = displayBtn; this. allowMultiline = allowMultiline;} private void button#click (object sender, EventArgs e) {if (this. onOpen! = Null) {this. OnOpen (this, null );}}}}
The following is the source code automatically generated by the system:
Namespace TEMS. Controls {partial class CTextBox {/// <summary> /// a required designer variable. /// </Summary> private System. ComponentModel. IContainer components = null; // <summary> /// clear all resources in use. /// </Summary> /// <param name = "disposing"> true if the managed resource should be released; otherwise, false. </Param> protected override void Dispose (bool disposing) {if (disposing & (components! = Null) {components. dispose ();} base. dispose (disposing );} # code generated by the region component designer /// <summary> /// the designer supports the required methods-do not // use the code editor to modify the content of this method. /// </Summary> private void InitializeComponent () {this. tableLayoutPanel1 = new System. windows. forms. tableLayoutPanel (); this. label1 = new System. windows. forms. label (); this. textBox1 = new System. windows. forms. textBox (); this. button1 = new System. windows. forms. button (); this. tableLayoutPanel1.SuspendLayout (); this. suspendLayout (); // tableLayoutPanel1 // this. tableLayoutPanel1.ColumnCount = 3; this. tableLayoutPanel1.ColumnStyles. add (new System. windows. forms. columnStyle (); this. tableLayoutPanel1.ColumnStyles. add (new System. windows. forms. columnStyle (System. windows. forms. sizeType. percent, 100F); this. tableLayoutPanel1.ColumnStyles. add (new System. windows. forms. columnStyle (); this. tableLayoutPanel1.Controls. add (this. label1, 0, 0); this. tableLayoutPanel1.Controls. add (this. textBox1, 1, 0); this. tableLayoutPanel1.Controls. add (this. button1, 2, 0); this. tableLayoutPanel1.Dock = System. windows. forms. dockStyle. fill; this. tableLayoutPanel1.Location = new System. drawing. point (0, 0); this. tableLayoutPanel1.Name = "tableLayoutPanel1"; this. tableLayoutPanel1.RowCount = 1; this. tableLayoutPanel1.RowStyles. add (new System. windows. forms. rowStyle (System. windows. forms. sizeType. percent, 100F); this. tableLayoutPanel1.Size = new System. drawing. size (250, 40); this. tableLayoutPanel1.TabIndex = 0; // label1 // this. label1.Anchor = System. windows. forms. anchorStyles. left; this. label1.AutoSize = true; this. label1.Font = new System. drawing. font ("", 11.25F, System. drawing. fontStyle. regular, System. drawing. graphicsUnit. point, (byte) (134); this. label1.Location = new System. drawing. point (3, 10); this. label1.Name = "label1"; this. label1.Size = new System. drawing. size (44, 20); this. label1.TabIndex = 0; this. label1.Text = "label"; this. label1.TextAlign = System. drawing. contentAlignment. middleLeft; // textBox1 // this. textBox1.Anchor = (System. windows. forms. anchorStyles) (System. windows. forms. anchorStyles. top | System. windows. forms. anchorStyles. bottom) | System. windows. forms. anchorStyles. left) | System. windows. forms. anchorStyles. right); this. textBox1.Font = new System. drawing. font ("", 11.25F, System. drawing. fontStyle. regular, System. drawing. graphicsUnit. point, (byte) (134); this. textBox1.Location = new System. drawing. point (53, 3); this. textBox1.Name = "textBox1"; this. textBox1.Size = new System. drawing. size (151, 27); this. textBox1.TabIndex = 1; // button1 // this. button1.Anchor = System. windows. forms. anchorStyles. none; this. button1.Location = new System. drawing. point (210, 8); this. button1.Name = "button1"; this. button1.Size = new System. drawing. size (37, 23); this. button1.TabIndex = 2; this. button1.Text = "... "; this. button1.UseVisualStyleBackColor = true; this. button1.Click + = new System. eventHandler (this. button#click); // CTextBox // this. autoScaleDimensions = new System. drawing. sizeF (6F, 12F); this. autoScaleMode = System. windows. forms. autoScaleMode. font; this. controls. add (this. tableLayoutPanel1); this. name = "CTextBox"; this. size = new System. drawing. size (250, 40); this. tableLayoutPanel1.ResumeLayout (false); this. tablelayoutpanel1.w.mlayout (); this. resumeLayout (false);} # endregion private System. windows. forms. tableLayoutPanel tableLayoutPanel1; private System. windows. forms. label label1; private System. windows. forms. textBox textBox1; private System. windows. forms. button button1 ;}}
The code is relatively simple and I will not elaborate on it here, but two custom methods are used:
General. GetPropertyInfo --- obtain attribute information based on the LINQ expression;
General. GetDisplayName --- obtain the display name based on the property information;
The method definition code is as follows (as described in my previous blog and my website www.zuowenjun.cn ):
/// <Summary> /// obtain the name to be displayed for the attribute /// </summary> /// <param name = "p"> </param> /// <returns> </returns> public static string GetDisplayName (PropertyInfo p) {string displayName = null; DisplayAttribute attr = p. getAttribute <DisplayAttribute> (); if (attr! = Null) {displayName = attr. name;} else {displayName = p. name;} return displayName;} // <summary> // obtain the specified attribute information (non-String-type packing and unpacking exist) /// </summary> /// <typeparam name = "T"> </typeparam> /// <param name = "select"> </param> /// <returns> </returns> public static PropertyInfo GetPropertyInfo <T> (Expression <Func <T, dynamic> select) {var body = select. body; if (body. nodeType = ExpressionType. convert) {var o = (body as UnaryExpression ). operand; return (o as MemberExpression ). member as PropertyInfo;} else if (body. nodeType = ExpressionType. memberAccess) {return (body as MemberExpression ). member as PropertyInfo;} return null ;}
If you think you can give a suggestion, if you think there are deficiencies, please point out, thank you!
In addition, to help you learn and use the series of controls, I have packaged and uploaded the source code. You can click the following link to download it:
Zwj-Controls.rar