Usuario
Windows Forms General FAQ

Debate general
-
This material should not be considered as a complete coverage of the frequently asked questions, but it tries to capture the high-level features with some depth in the Windows Forms General areas.
1. TREEVIEW
1.1 How to retain an expanded state after reloading TreeView?
1.2 How to show hierarchical data in TreeView?
1.3 How do I implement Drag and Drop support between two TreeViews?
1.4 How to hide CheckBoxes for child nodes when CheckBoxes is set to true.
2. TEXTBOX
2.1 How do I programmatically position the cursor on a given line and character in a RichTextBox?
2.2 How to save RTF-formatted data from a Windows Forms RTF control to SQL Server?
2.3 How to get the current character’s color of a RichTextBox?
2.4 How to make the scroll smoother in a RichTextBox?
2.5 If a rich text box contains images and text, is it possible to detect when an image is clicked?
2.6 How to make a TextBox only accept digits?
3. COMBOBOX
3.1 How do I setup a ComboBox to bind to a Lookup table?
3.2 How to add a ‘please select’ item to ComboBox?
3.3 How to make the drop down part of the combo box wide enough to see all items?
4. LISTBOX
4.1 How to display tooltip on individual items in a ListBox?
4.2 How to add a business object to the item collection of a ListBox and display expected text?
5. MENUSTRIP
5.1 What’s the relationship between MainMenu and MenuStrip?
5.2 How do I disable the MenuStrip's ALT-key action?
5.3 How to set the count of items displayed in a MenuStripItem’s DropDown list?
6. TOOLSTRIP
6.1 How to set the height of ToolStrip and ToolStripItem?
6.2 How to make a ToolStripTextBox hide true text and replace them with '*'?
6.3 Why a ToolStripButton didn’t cause the validation?
7. TABPAGE
- Editado Kira Qian miércoles, 31 de diciembre de 2008 9:59 edit4
martes, 4 de diciembre de 2007 12:31
Todas las respuestas
-
1.1 How to retain an expanded state after reloading TreeView?
That's going to be difficult. Other parent nodes might have been expanded. Capturing the entire state of the tree is tough. The need to refresh the entire tree is odd. You can just refresh the node contents of the existing tree. You could use the TreeNode.Tag property to retain some kind of reference to the source data.
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2203734&SiteID=1martes, 4 de diciembre de 2007 12:34 -
1.2 How to show hierarchical data in TreeView?
First you should create all tree nodes using these records, and then you can use a hash table to store these tree nodes. Finally loop through the hash table and add these tree nodes hierarchically.
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1774847&SiteID=1martes, 4 de diciembre de 2007 12:43 -
1.3 How do I implement Drag and Drop support between two TreeViews?
In a posting in the Microsoft.Windows.Forms newsgroup, Brian Roder (Microsoft) gives VB.Net code snippets to handle the DragEnter, ItemDrag and DragDrop events that provide a solution to this problem. Here are some sample handlers written in C#.
Code Blockprivate void treeView2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
TreeNode newNode;
if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
{
Point pt;
TreeNode destinationNode;
pt = treeView2.PointToClient(new Point(e.X, e.Y));
destinationNode = treeView2.GetNodeAt(pt);
newNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
if (!destinationNode.Equals(newNode))
{
//destinationNode.Nodes.Add(newNode.Clone());
destinationNode.Nodes.Add((TreeNode)newNode.Clone());
destinationNode.Expand();
//Remove original node
newNode.Remove();
}
}
}
private void treeView2_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void treeView2_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
martes, 4 de diciembre de 2007 12:48 -
1.4 How to hide CheckBoxes for child nodes when CheckBoxes is set to true.
To enable this feature, we should owner draw the tree node. We can set the TreeView.DrawMode property to OwnerDrawAll and handle the DrawNode event. Try something like the following in this handler.
Code Blockprivate void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (IsThirdLevel(e.Node))
{
Color backColor, foreColor;
if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
{
backColor = SystemColors.Highlight;
foreColor = SystemColors.HighlightText;
}
else if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
{
backColor = SystemColors.HotTrack;
foreColor = SystemColors.HighlightText;
}
else
{
backColor = e.Node.BackColor;
foreColor = e.Node.ForeColor;
}
using (SolidBrush brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Node.Bounds);
}
TextRenderer.DrawText(e.Graphics, e.Node.Text,
this.treeView.Font, e.Node.Bounds, foreColor, backColor);if ((e.State & TreeNodeStates.Focused) == TreeNodeStates.Focused)
{
ControlPaint.DrawFocusRectangle(e.Graphics, e.Node.Bounds,
foreColor, backColor);}
e.DrawDefault = false;
}
else
{
e.DrawDefault = true;
}
}
private static bool IsThirdLevel(TreeNode node)
{
return node.Parent != null && node.Parent.Parent != null;
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1883238&SiteID=1martes, 4 de diciembre de 2007 12:52 -
2.1 How do I programmatically position the cursor on a given line and character in a RichTextBox?
The RichTextBox control contains a Lines array property, one entry for every line. Each line entry has a Length property. With this information, you can position the selection cursor using code such as:
Code Blockprivate void GoToLineAndColumn(RichTextBox rtb, int line, int column)
{
rtb.Focus();
if (line < 0 || column < 0)
{
rtb.SelectionStart = 0;
}
else
{
if (line > rtb.Lines.Length - 1)
{
rtb.SelectionStart = rtb.GetFirstCharIndexFromLine(rtb.Lines.Length - 1)
+ rtb.Lines[rtb.Lines.Length - 1].Length;}
else
{
int firstCharIndexOfline = rtb.GetFirstCharIndexFromLine(line);
int textlengthOfline;
textlengthOfline = rtb.Lines[line].Length;
if (column > textlengthOfline)
column = textlengthOfline;
rtb.SelectionStart = firstCharIndexOfline + column;
}
}
}
martes, 4 de diciembre de 2007 12:56 -
2.2 How to save RTF-formatted data from a Windows Forms RTF control to SQL Server?
In this situation, using a RichTextBox is the easiest way; we can just bind the field to the Rtf property of RichTextBox.
Code BlockBinding bd =new Binding("Rtf", dt, "descs",true);Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2246017&SiteID=1martes, 4 de diciembre de 2007 13:01 -
2.3 How to get the current character’s color of a RichTextBox?
The RichTextBox has provided you a property named SelectionColor; you can use this property to get the current character’s color
private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
int index = richTextBox1.GetCharIndexFromPosition(e.Location);
richTextBox1.SelectionStart = index;
label1.Text = richTextBox1.SelectionColor.ToString();
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2139967&SiteID=1martes, 4 de diciembre de 2007 13:03 -
2.4 How to make the scroll smoother in a RichTextBox?
Try to use two windows API functions, GetScrollPos and PostMessage. The GetScrollPos is used to get the current position of RichTextBox, and the PostMessage is used to place a scroll-down message in the message queue associated with the thread that created the window.
Code Block<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="PostMessage")> _
Public Shared Function PostMessage(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="GetScrollPos")> _
Public Shared Function GetScrollPos(ByVal hwnd As Integer, ByVal nBar As Integer) As Integer
End Function
Public Const WM_VSCROLL As Integer = 277
Public Const SB_THUMBPOSITION As Integer = 4
Public Const SBS_VERT As Integer = 1
Private previousPos As Integer = 0
Private Sub RTBAutoScroll_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Me.RichTextBox1.[Select](0, 0)
Me.RichTextBox1.ScrollToCaret()
Me.Timer1.Interval = 300
AddHandler Me.Timer1.Tick, AddressOf timer1_Tick
Dim td As New DateTime()
Me.Text = td.ToString()
End Sub
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As EventArgs)
Dim currentPos As Integer = GetScrollPos(CInt(Me.richTextBox1.Handle), SBS_VERT)
If previousPos <> currentPos OrElse currentPos = 0 Then
previousPos = currentPos
PostMessage(CInt(Me.richTextBox1.Handle), WM_VSCROLL, SB_THUMBPOSITION + 65536 * (currentPos + 1), 0)
End If
End Sub
Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If Button1.Text = "Auto Scroll" Then
Button1.Text = "Pause"
Timer1.Enabled = True
ElseIf Button1.Text = "Pause" Then
Button1.Text = "Auto Scroll"
Timer1.Enabled = False
End If
End Sub
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2102412&SiteID=1martes, 4 de diciembre de 2007 13:06 -
2.5 If a rich text box contains images and text, is it possible to detect when an image is clicked?
The Rich Text Format (RTF) Specification says, pictures are destinations, and begin with the \pict control word. We can try to judge the SelectedRtf string to see if this contains the \pict when click on the RichTextBox.
Code Blockthis.richTextBox1.MouseClick += new MouseEventHandler(richTextBox1_MouseClick);
void richTextBox1_MouseClick(object sender, MouseEventArgs e)
{
if (this.richTextBox1.SelectedRtf.IndexOf(@"\pict") != -1 &&
this.richTextBox1.SelectionType == RichTextBoxSelectionTypes.Object){
MessageBox.Show("Image has been clicked!");
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2191267&SiteID=1martes, 4 de diciembre de 2007 13:09 -
2.6 How to make a TextBox only accept digits?
You can handle the textbox's KeyPress event and if the char passed in is not digits, mark the events argument as showing that the character has been handled. Below is a derived TextBox that only accepts digits (and control characters such as backspace).
Code Blockpublic class NumbersOnlyTextBox : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (!(char.IsDigit(e.KeyChar) || char.IsControl(e.KeyChar)))
e.Handled = true;
}
}
martes, 4 de diciembre de 2007 13:11 -
3.1 How do I setup a ComboBox to bind to a Lookup table?
A common use of a ComboBox in a data bound application is as a lookup based UI control. From a database perspective, a Lookup control is used to provide the “lookup” values for a foreign key. For example, assume you have a customer table with a “StateID” where the “StateID” is a foreign key into a “States” table. From a UI perspective, you’d like to allow the user to select a State via a ComboBox. To do this, you use Complex Binding to bind the ComboBox to the States table (setting the ComboBox.DisplayMember and ComboBox.ValueMember) and use Simple List Binding to bind the ComboBox SelectedValue to the Customer “StateID”.
Code BlockCustomer cust = new Customer("Joe", "WA");
this.statesCB.DisplayMember = "Name";
this.statesCB.ValueMember = "Code";
this.statesCB.DataSource = statesTable;
this.statesCB.DataBindings.Add("SelectedValue", cust, "StateID", true);
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1753655&SiteID=1miércoles, 5 de diciembre de 2007 13:48 -
3.2 How to add a ‘please select’ item to ComboBox?
If the ComboBox is not data bound, you can add an item to the item collection.
Code Blockthis.comboBox1.Items.Insert(0, "please select");
this.comboBox1.SelectedIndex = 0;
If the ComboBox is data bound, you will need to add this item to the data source
Code BlockCustomer cust = new Customer("Joe", null);
DataRow row = statesTable.NewRow();
row["Name"] = " please select";
row["Code"] = DBNull.Value;
statesTable.Rows.Add(row);
this.statesCB.DisplayMember = "Name";
this.statesCB.ValueMember = "Code";
this.statesCB.DataSource = statesTable;
this.statesCB.DataBindings.Add("SelectedValue", cust, "StateID", true);
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1769727&SiteID=1miércoles, 5 de diciembre de 2007 13:51 -
3.3 How to make the drop down part of the combo box wide enough to see all items?
You can set the DropDownWidth of a combo box to make the combo box dropdown wide enough.
Code Blockstring s = "this is a really, really, really, really, really, long string";
Graphics g = Graphics.FromHwnd(this.Handle);
SizeF size = g.MeasureString(s, comboBox1.Font);
comboBox1.DropDownWidth = Convert.ToInt32(size.Width);
this.comboBox1.Items.Add(s);
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2281333&SiteID=1miércoles, 5 de diciembre de 2007 13:54 -
4.1 How to display tooltip on individual items in a ListBox?
If you want to display tooltip on individual items in a ListBox, here is a quick easy way. First create a method to handle mouse move events, and then hook it to the MouseMove event of the ListBox. You will also need a ToolTip object as a member variable for the form. The code required to create and update the tooltip is:
Code Blockprivate void onMouseMove(object sender, MouseEventArgs e)
{
if (sender is ListBox)
{
ListBox listBox = (ListBox)sender;
Point point = new Point(e.X, e.Y);
int hoverIndex = listBox.IndexFromPoint(point);
if (hoverIndex >= 0 && hoverIndex < listBox.Items.Count)
{
tt.SetToolTip(listBox, listBox.Items[hoverIndex].ToString());
}
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2073944&SiteID=1miércoles, 5 de diciembre de 2007 13:56 -
4.2 How to add a business object to the item collection of a ListBox and display expected text?
The most common way to achieve this is to set the DiaplayMember to the Proterty name of your business object.
The second way is to use a TypeConverter to convert the business object. You need to custom a TypeConverter and override its ConvertTo method. Check the following sample code.
Code Block[TypeConverter(typeof(BusinessTypeConvert))]
class BusinessObject
{
int id;
public int Id
{
get { return id; }
set { id = value; }
}
string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
class BusinessTypeConvert :TypeConverter
{
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
return ((BusinessObject)value).Name;
return base.ConvertTo(context, culture, value, destinationType);
}
}
The third choice is to override the ToString method of your business object and return the expected text in this method. But this is not recommended since ToString method is usually used to return some information about the class.
miércoles, 5 de diciembre de 2007 13:59 -
I want to use two buttons to move items back and forth. For example, ‘L->R’ moves items from left ListBox to right ListBox, ‘R->L’ moves items form right ListBox to left ListBox.
Place two ListBoxes with two buttons between them. One button with Text ‘R->L’, and the other ‘L->R’.
In the L->R click event handler:
Code Blockforeach (int index in listBox1.SelectedIndices)
{
listBox2.Items.Add(listBox1.Items[index]);
listBox1.Items.RemoveAt(index);
}
In the R-L click event handler:
Code Blockforeach (int index in listBox2.SelectedIndices)
{
listBox1.Items.Add(listBox2.Items[index]);
listBox2.Items.RemoveAt(index);
}
For both ListBoxes, the property SelectionMode should be set to MultiSimple. And place several items in one or both of the ListBoxes
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1830319&SiteID=1miércoles, 5 de diciembre de 2007 14:03 -
5.1 What’s the relationship between MainMenu and MenuStrip?
MenuStrip is a complete replacement for MainMenu and has nothing in common with that control. The old MainMenu was built on top of the built-in Windows support for menus. The GetClientRect() API function automatically deducts the menu size from the client rectangle. MenuStrip doesn't use Windows menus, thus GetClientRect() returns the size of the window's client area, disregarding the space taken up by the MenuStrip. The same is true for any other window edge adornments like StatusStrip and ToolStrip, or any docked panels for that matter.
miércoles, 5 de diciembre de 2007 14:05 -
5.2 How do I disable the MenuStrip's ALT-key action?
Just override the ProcessDialogKey in your form, as:
Code Blockprotected override bool ProcessDialogKey(Keys keyData)
{
if ((keyData & Keys.Alt) == Keys.Alt)
return true;
else
return base.ProcessDialogKey(keyData);
}
miércoles, 5 de diciembre de 2007 14:06 -
5.3 How to set the count of items displayed in a MenuStripItem’s DropDown list?
If there are too many items in MenuStripItem’s item collection, it will use a lot of space to show these menus. I want to show only eight (or other number) menus. How can I achieve this?
We will need to set the AutoSize of the MenuStripItem’s DropDown portion to false and inputs its height.
Code Blockthis.fileToolStripMenuItem.DropDown.AutoSize = false;
this.fileToolStripMenuItem.DropDown.Height = 200;
miércoles, 5 de diciembre de 2007 14:08 -
6.1 How to set the height of ToolStrip and ToolStripItem?
Try to set both ToolStrip and ToolStripItem’s AutoSize to false, and make sure your ToolStrip’s height is greater than all your ToolStripItems. Try something like the following:
Code Blockthis.toolStrip1.AutoSize = false;
this.toolStripButton1.AutoSize = false;
this.toolStripButton2.AutoSize = false;
this.toolStripButton3.AutoSize = false;
this.toolStripButton1.Height = 20;
this.toolStripButton2.Height = 40;
this.toolStripButton3.Height = 60;
this.toolStrip1.Height = 65;
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2080536&SiteID=1miércoles, 5 de diciembre de 2007 14:10 -
6.2 How to make a ToolStripTextBox hide true text and replace them with '*'?
The ToolStripTextBox actually contains a TextBox and use this TextBox to allow the user to type in. You can get the TextBox hosted in the ToolStripTextBox and set the PasswordChar property.
Code Blockif (this.toolStripTextBox1.Control is TextBox)
{
TextBox tb = this.toolStripTextBox1.Control as TextBox;
tb.PasswordChar = '*';
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2042939&SiteID=1miércoles, 5 de diciembre de 2007 14:12 -
6.3 Why a ToolStripButton didn’t cause the validation?
By default, toolbars and menus do not need focus when you click on it, thus it does not force validation for controls. A related question is that why it didn’t commit the data to the database when clicking on a toolstrip. To solve this problem, add the following line of code in the click event to force the validation.
Code Blockthis.Validate();//this refers to your form
miércoles, 5 de diciembre de 2007 14:14 -
7.1 How to put a close button on TabPage header?
We can build a custom TabControl and override its OnDrawItem method in which you paint the "close button", then do the hit testing and close the tab when the "close button" is clicked. The following article demonstrates the idea in more detail:
http://www.codeproject.com/cs/miscctrl/firefoxtabcontrol.asp
miércoles, 5 de diciembre de 2007 14:15 -
7.2 How to hide the header of TabPage?
Add a new class to your project, paste the code shown below and build the project. You can now drop the control from the top of the toolbox onto your form. At design time, the control looks like a regular TabControl. At run-time, you only see the pages. Use the SelectedIndex property to step through the pages.
Code Blockusing System;
using System.Windows.Forms;
public class WizardPages : TabControl
{
protected override void WndProc(ref Message m)
{
// Hide tabs by trapping the TCM_ADJUSTRECT message
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
else
base.WndProc(ref m);
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1518961&SiteID=1miércoles, 5 de diciembre de 2007 14:17 -
Adding the "Please select..." row to the data source breaks the encapsulation of your layers.
It is better to override the painting of the ComboBox to show the "Please select..." hint. Also, this allows you to show this hint without it being selectable in the dropdown's content. And it let's you add ComboBoxes with a default text without writing all this (I didn't find a way to clear the selection after data binding without coding it, otherwise there would be nothing to write).
I wrote a blog post about this issue and provided a ComboBox extension for this : http://www.byteauthor.com/2010/08/inner-label-in-combobox/
martes, 3 de agosto de 2010 20:02 -
Dear Rong,
you question were remove my most of the peril about treeview,
thanks for the same.
Pl. Mark/Proposed as Answer if found your solution Vote as Helpful if related to your topic. Always Motivate others by performing this Action.
lunes, 17 de septiembre de 2012 16:27