以下为工作中遇到的,备注一下

先需要几个辅助类

 #region GripBounds

 using System.Drawing;
internal struct GripBounds
{
private const int GripSize = ;
private const int CornerGripSize = GripSize << ; public GripBounds(Rectangle clientRectangle)
{
this.clientRectangle = clientRectangle;
} private Rectangle clientRectangle;
public Rectangle ClientRectangle
{
get { return clientRectangle; }
//set { clientRectangle = value; }
} public Rectangle Bottom
{
get
{
Rectangle rect = ClientRectangle;
rect.Y = rect.Bottom - GripSize + ;
rect.Height = GripSize;
return rect;
}
} public Rectangle BottomRight
{
get
{
Rectangle rect = ClientRectangle;
rect.Y = rect.Bottom - CornerGripSize + ;
rect.Height = CornerGripSize;
rect.X = rect.Width - CornerGripSize + ;
rect.Width = CornerGripSize;
return rect;
}
} public Rectangle Top
{
get
{
Rectangle rect = ClientRectangle;
rect.Height = GripSize;
return rect;
}
} public Rectangle TopRight
{
get
{
Rectangle rect = ClientRectangle;
rect.Height = CornerGripSize;
rect.X = rect.Width - CornerGripSize + ;
rect.Width = CornerGripSize;
return rect;
}
} public Rectangle Left
{
get
{
Rectangle rect = ClientRectangle;
rect.Width = GripSize;
return rect;
}
} public Rectangle BottomLeft
{
get
{
Rectangle rect = ClientRectangle;
rect.Width = CornerGripSize;
rect.Y = rect.Height - CornerGripSize + ;
rect.Height = CornerGripSize;
return rect;
}
} public Rectangle Right
{
get
{
Rectangle rect = ClientRectangle;
rect.X = rect.Right - GripSize + ;
rect.Width = GripSize;
return rect;
}
} public Rectangle TopLeft
{
get
{
Rectangle rect = ClientRectangle;
rect.Width = CornerGripSize;
rect.Height = CornerGripSize;
return rect;
}
}
} #endregion
 #region UnsafeMethods

 using System;
using System.Drawing;
using System.Runtime.InteropServices;
internal class UnsafeMethods
{
public static readonly IntPtr TRUE = new IntPtr();
public static readonly IntPtr FALSE = new IntPtr(); public const int WM_LBUTTONDOWN = 0x201;
public const int WM_RBUTTONDOWN = 0x204;
public const int WM_MBUTTONDOWN = 0x207;
public const int WM_NCLBUTTONDOWN = 0x0A1;
public const int WM_NCRBUTTONDOWN = 0x0A4;
public const int WM_NCMBUTTONDOWN = 0x0A7;
public const int WM_NCCALCSIZE = 0x0083;
public const int WM_NCHITTEST = 0x0084;
public const int WM_NCPAINT = 0x0085;
public const int WM_NCACTIVATE = 0x0086;
public const int WM_MOUSELEAVE = 0x02A3;
public const int WS_EX_NOACTIVATE = 0x08000000;
public const int HTTRANSPARENT = -;
public const int HTLEFT = ;
public const int HTRIGHT = ;
public const int HTTOP = ;
public const int HTTOPLEFT = ;
public const int HTTOPRIGHT = ;
public const int HTBOTTOM = ;
public const int HTBOTTOMLEFT = ;
public const int HTBOTTOMRIGHT = ;
public const int WM_USER = 0x0400;
public const int WM_REFLECT = WM_USER + 0x1C00;
public const int WM_COMMAND = 0x0111;
public const int CBN_DROPDOWN = ;
public const int WM_GETMINMAXINFO = 0x0024; public enum TrackerEventFlags : uint
{
TME_HOVER = 0x00000001,
TME_LEAVE = 0x00000002,
TME_QUERY = 0x40000000,
TME_CANCEL = 0x80000000
} [DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hwnd, IntPtr hDC); [DllImport("user32")]
public static extern bool TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack); [DllImport("user32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); internal static int HIWORD(int n)
{
return (n >> ) & 0xffff;
} internal static int HIWORD(IntPtr n)
{
return HIWORD(unchecked((int)(long)n));
} internal static int LOWORD(int n)
{
return n & 0xffff;
} internal static int LOWORD(IntPtr n)
{
return LOWORD(unchecked((int)(long)n));
} [StructLayout(LayoutKind.Sequential)]
internal struct TRACKMOUSEEVENT
{
public uint cbSize;
public uint dwFlags;
public IntPtr hwndTrack;
public uint dwHoverTime;
} [StructLayout(LayoutKind.Sequential)]
internal struct MINMAXINFO
{
public Point reserved;
public Size maxSize;
public Point maxPosition;
public Size minTrackSize;
public Size maxTrackSize;
} #region RECT structure [StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int left;
public int top;
public int right;
public int bottom; public RECT(int left, int top, int right, int bottom)
{
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
} public Rectangle Rect
{
get
{
return new Rectangle(
this.left,
this.top,
this.right - this.left,
this.bottom - this.top);
}
} public static RECT FromXYWH(int x, int y, int width, int height)
{
return new RECT(x,
y,
x + width,
y + height);
} public static RECT FromRectangle(Rectangle rect)
{
return new RECT(rect.Left,
rect.Top,
rect.Right,
rect.Bottom);
}
} #endregion RECT structure #region WINDOWPOS [StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPOS
{
internal IntPtr hwnd;
internal IntPtr hWndInsertAfter;
internal int x;
internal int y;
internal int cx;
internal int cy;
internal uint flags;
}
#endregion #region NCCALCSIZE_PARAMS
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowstructures/nccalcsize_params.asp
[StructLayout(LayoutKind.Sequential)]
public struct NCCALCSIZE_PARAMS
{
/// <summary>
/// Contains the new coordinates of a window that has been moved or resized, that is, it is the proposed new window coordinates.
/// </summary>
public RECT rectProposed;
/// <summary>
/// Contains the coordinates of the window before it was moved or resized.
/// </summary>
public RECT rectBeforeMove;
/// <summary>
/// Contains the coordinates of the window's client area before the window was moved or resized.
/// </summary>
public RECT rectClientBeforeMove;
/// <summary>
/// Pointer to a WINDOWPOS structure that contains the size and position values specified in the operation that moved or resized the window.
/// </summary>
public WINDOWPOS lpPos;
} #endregion
} #endregion
 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using VS = System.Windows.Forms.VisualStyles; /*
<li>Base class for custom tooltips.</li>
<li>Office-2007-like tooltip class.</li>
*/
namespace ZhuoYueE.Bpc.Controls
{
/// <summary>
/// Represents a pop-up window.
/// </summary>
[ToolboxItem(false)]
public partial class PopupForm : ToolStripDropDown
{
#region " Fields & Properties " private Control content;
/// <summary>
/// Gets the content of the pop-up.
/// </summary>
public Control Content
{
get { return content; }
} private bool fade;
/// <summary>
/// Gets a value indicating whether the <see cref="PopupControl.Popup"/> uses the fade effect.
/// </summary>
/// <value><c>true</c> if pop-up uses the fade effect; otherwise, <c>false</c>.</value>
/// <remarks>To use the fade effect, the FocusOnOpen property also has to be set to <c>true</c>.</remarks>
public bool UseFadeEffect
{
get { return fade; }
set
{
if (fade == value) return;
fade = value;
}
} private bool focusOnOpen = true;
/// <summary>
/// Gets or sets a value indicating whether the content should receive the focus after the pop-up has been opened.
/// </summary>
/// <value><c>true</c> if the content should be focused after the pop-up has been opened; otherwise, <c>false</c>.</value>
/// <remarks>If the FocusOnOpen property is set to <c>false</c>, then pop-up cannot use the fade effect.</remarks>
public bool FocusOnOpen
{
get { return focusOnOpen; }
set { focusOnOpen = value; }
} private bool acceptAlt = true;
/// <summary>
/// Gets or sets a value indicating whether presing the alt key should close the pop-up.
/// </summary>
/// <value><c>true</c> if presing the alt key does not close the pop-up; otherwise, <c>false</c>.</value>
public bool AcceptAlt
{
get { return acceptAlt; }
set { acceptAlt = value; }
} private PopupForm ownerPopup;
private PopupForm childPopup; private bool _resizable;
private bool resizable;
/// <summary>
/// Gets or sets a value indicating whether the <see cref="PopupControl.Popup" /> is resizable.
/// </summary>
/// <value><c>true</c> if resizable; otherwise, <c>false</c>.</value>
public bool Resizable
{
get { return resizable && _resizable; }
set { resizable = value; }
} private ToolStripControlHost host; private Size minSize;
/// <summary>
/// Gets or sets a minimum size of the pop-up.
/// </summary>
/// <returns>An ordered pair of type <see cref="T:System.Drawing.Size" /> representing the width and height of a rectangle.</returns>
public new Size MinimumSize
{
get { return minSize; }
set { minSize = value; }
} private Size maxSize;
/// <summary>
/// Gets or sets a maximum size of the pop-up.
/// </summary>
/// <returns>An ordered pair of type <see cref="T:System.Drawing.Size" /> representing the width and height of a rectangle.</returns>
public new Size MaximumSize
{
get { return maxSize; }
set { maxSize = value; }
} private bool _isOpen; public bool IsOpen
{
get { return _isOpen; }
} /// <summary>
/// Gets parameters of a new window.
/// </summary>
/// <returns>An object of type <see cref="T:System.Windows.Forms.CreateParams" /> used when creating a new window.</returns>
protected override CreateParams CreateParams
{
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= UnsafeMethods.WS_EX_NOACTIVATE;
return cp;
}
} #endregion #region " Constructors " /// <summary>
/// Initializes a new instance of the <see cref="PopupControl.Popup"/> class.
/// </summary>
/// <param name="content">The content of the pop-up.</param>
/// <remarks>
/// Pop-up will be disposed immediately after disposion of the content control.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException"><paramref name="content" /> is <code>null</code>.</exception>
public PopupForm(Control content)
{
if (content == null)
{
throw new ArgumentNullException("content");
}
this.content = content;
this.fade = SystemInformation.IsMenuAnimationEnabled && SystemInformation.IsMenuFadeEnabled;
this._resizable = true;
AutoSize = false;
DoubleBuffered = true;
ResizeRedraw = true;
host = new ToolStripControlHost(content);
Padding = Margin = host.Padding = host.Margin = Padding.Empty;
MinimumSize = content.MinimumSize;
content.MinimumSize = content.Size;
MaximumSize = content.MaximumSize;
content.MaximumSize = content.Size;
Size = content.Size;
content.Location = Point.Empty;
Items.Add(host);
content.Disposed += delegate(object sender, EventArgs e)
{
content = null;
Dispose(true);
};
content.RegionChanged += delegate(object sender, EventArgs e)
{
UpdateRegion();
};
content.Paint += delegate(object sender, PaintEventArgs e)
{
PaintSizeGrip(e);
};
UpdateRegion();
} #endregion #region " Methods " /// <summary>
/// Processes a dialog box key.
/// </summary>
/// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys" /> values that represents the key to process.</param>
/// <returns>
/// true if the key was processed by the control; otherwise, false.
/// </returns>
protected override bool ProcessDialogKey(Keys keyData)
{
if (acceptAlt && ((keyData & Keys.Alt) == Keys.Alt))
{
if ((keyData & Keys.F4) != Keys.F4)
{
return false;
}
else
{
this.Close();
}
}
return base.ProcessDialogKey(keyData);
} /// <summary>
/// Updates the pop-up region.
/// </summary>
protected void UpdateRegion()
{
if (this.Region != null)
{
this.Region.Dispose();
this.Region = null;
}
if (content.Region != null)
{
this.Region = content.Region.Clone();
}
} /// <summary>
/// Shows the pop-up window below the specified control.
/// </summary>
/// <param name="control">The control below which the pop-up will be shown.</param>
/// <remarks>
/// When there is no space below the specified control, the pop-up control is shown above it.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException"><paramref name="control"/> is <code>null</code>.</exception>
public void Show(Control control)
{
Show(control, control.ClientRectangle);
} public void Show(Control control, bool center)
{
Show(control, control.ClientRectangle, center);
} /// <summary>
/// Shows the pop-up window below the specified area of the specified control.
/// </summary>
/// <param name="control">The control used to compute screen location of specified area.</param>
/// <param name="area">The area of control below which the pop-up will be shown.</param>
/// <remarks>
/// When there is no space below specified area, the pop-up control is shown above it.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException"><paramref name="control"/> is <code>null</code>.</exception>
public void Show(Control control, Rectangle area)
{
Show(control, area, false);
} public void Show(Control control, Rectangle area, bool center)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
SetOwnerItem(control);
resizableTop = resizableLeft = false;
Point location = control.PointToScreen(new Point(area.Left, area.Top + area.Height));
Rectangle screen = Screen.FromControl(control).WorkingArea;
if (center)
{
if (location.X + (area.Width + Size.Width) / > screen.Right)
{
resizableLeft = true;
location.X = screen.Right - Size.Width;
}
else
{
resizableLeft = true;
location.X = location.X - (Size.Width - area.Width) / ;
}
}
else
{
if (location.X + Size.Width > (screen.Left + screen.Width))
{
resizableLeft = true;
location.X = (screen.Left + screen.Width) - Size.Width;
}
} if (location.Y + Size.Height > (screen.Top + screen.Height))
{
resizableTop = true;
location.Y -= Size.Height + area.Height;
}
location = control.PointToClient(location);
Show(control, location, ToolStripDropDownDirection.BelowRight);
} private const int frames = ;
private const int totalduration = ;
private const int frameduration = totalduration / frames;
/// <summary>
/// Adjusts the size of the owner <see cref="T:System.Windows.Forms.ToolStrip" /> to accommodate the <see cref="T:System.Windows.Forms.ToolStripDropDown" /> if the owner <see cref="T:System.Windows.Forms.ToolStrip" /> is currently displayed, or clears and resets active <see cref="T:System.Windows.Forms.ToolStripDropDown" /> child controls of the <see cref="T:System.Windows.Forms.ToolStrip" /> if the <see cref="T:System.Windows.Forms.ToolStrip" /> is not currently displayed.
/// </summary>
/// <param name="visible">true if the owner <see cref="T:System.Windows.Forms.ToolStrip" /> is currently displayed; otherwise, false.</param>
protected override void SetVisibleCore(bool visible)
{
double opacity = Opacity;
if (visible && fade && focusOnOpen) Opacity = ;
base.SetVisibleCore(visible);
if (!visible || !fade || !focusOnOpen) return;
for (int i = ; i <= frames; i++)
{
if (i > )
{
System.Threading.Thread.Sleep(frameduration);
}
Opacity = opacity * (double)i / (double)frames;
}
Opacity = opacity;
} private bool resizableTop;
private bool resizableLeft; private void SetOwnerItem(Control control)
{
if (control == null)
{
return;
}
if (control is PopupForm)
{
PopupForm popupControl = control as PopupForm;
ownerPopup = popupControl;
ownerPopup.childPopup = this;
OwnerItem = popupControl.Items[];
return;
}
if (control.Parent != null)
{
SetOwnerItem(control.Parent);
}
} /// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.SizeChanged" /> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
protected override void OnSizeChanged(EventArgs e)
{
content.MinimumSize = Size;
content.MaximumSize = Size;
content.Size = Size;
content.Location = Point.Empty;
base.OnSizeChanged(e);
} /// <summary>
/// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Opening" /> event.
/// </summary>
/// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs" /> that contains the event data.</param>
protected override void OnOpening(CancelEventArgs e)
{
if (content.IsDisposed || content.Disposing)
{
e.Cancel = true;
return;
}
UpdateRegion();
base.OnOpening(e);
} /// <summary>
/// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Opened" /> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
protected override void OnOpened(EventArgs e)
{
if (ownerPopup != null)
{
ownerPopup._resizable = false;
}
if (focusOnOpen)
{
content.Focus();
}
_isOpen = true;
base.OnOpened(e);
} /// <summary>
/// Raises the <see cref="E:System.Windows.Forms.ToolStripDropDown.Closed"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.ToolStripDropDownClosedEventArgs"/> that contains the event data.</param>
protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
{
if (ownerPopup != null)
{
ownerPopup._resizable = true;
}
_isOpen = false;
base.OnClosed(e);
} #endregion #region " Resizing Support " /// <summary>
/// Processes Windows messages.
/// </summary>
/// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message" /> to process.</param>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
if (InternalProcessResizing(ref m, false))
{
return;
}
base.WndProc(ref m);
} /// <summary>
/// Processes the resizing messages.
/// </summary>
/// <param name="m">The message.</param>
/// <returns>true, if the WndProc method from the base class shouldn't be invoked.</returns>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public bool ProcessResizing(ref Message m)
{
return InternalProcessResizing(ref m, true);
} [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
private bool InternalProcessResizing(ref Message m, bool contentControl)
{
if (m.Msg == UnsafeMethods.WM_NCACTIVATE && m.WParam != IntPtr.Zero && childPopup != null && childPopup.Visible)
{
childPopup.Hide();
}
if (!Resizable)
{
return false;
}
if (m.Msg == UnsafeMethods.WM_NCHITTEST)
{
return OnNcHitTest(ref m, contentControl);
}
else if (m.Msg == UnsafeMethods.WM_GETMINMAXINFO)
{
return OnGetMinMaxInfo(ref m);
}
return false;
} [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
private bool OnGetMinMaxInfo(ref Message m)
{
UnsafeMethods.MINMAXINFO minmax = (UnsafeMethods.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(UnsafeMethods.MINMAXINFO));
minmax.maxTrackSize = this.MaximumSize;
minmax.minTrackSize = this.MinimumSize;
Marshal.StructureToPtr(minmax, m.LParam, false);
return true;
} private bool OnNcHitTest(ref Message m, bool contentControl)
{
int x = UnsafeMethods.LOWORD(m.LParam);
int y = UnsafeMethods.HIWORD(m.LParam);
Point clientLocation = PointToClient(new Point(x, y)); GripBounds gripBouns = new GripBounds(contentControl ? content.ClientRectangle : ClientRectangle);
IntPtr transparent = new IntPtr(UnsafeMethods.HTTRANSPARENT); if (resizableTop)
{
if (resizableLeft && gripBouns.TopLeft.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTTOPLEFT;
return true;
}
if (!resizableLeft && gripBouns.TopRight.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTTOPRIGHT;
return true;
}
if (gripBouns.Top.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTTOP;
return true;
}
}
else
{
if (resizableLeft && gripBouns.BottomLeft.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTBOTTOMLEFT;
return true;
}
if (!resizableLeft && gripBouns.BottomRight.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTBOTTOMRIGHT;
return true;
}
if (gripBouns.Bottom.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTBOTTOM;
return true;
}
}
if (resizableLeft && gripBouns.Left.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTLEFT;
return true;
}
if (!resizableLeft && gripBouns.Right.Contains(clientLocation))
{
m.Result = contentControl ? transparent : (IntPtr)UnsafeMethods.HTRIGHT;
return true;
}
return false;
} private VS.VisualStyleRenderer sizeGripRenderer;
/// <summary>
/// Paints the sizing grip.
/// </summary>
/// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
public void PaintSizeGrip(PaintEventArgs e)
{
if (e == null || e.Graphics == null || !resizable)
{
return;
}
Size clientSize = content.ClientSize;
using (Bitmap gripImage = new Bitmap(0x10, 0x10))
{
using (Graphics g = Graphics.FromImage(gripImage))
{
if (Application.RenderWithVisualStyles)
{
if (this.sizeGripRenderer == null)
{
this.sizeGripRenderer = new VS.VisualStyleRenderer(VS.VisualStyleElement.Status.Gripper.Normal);
}
this.sizeGripRenderer.DrawBackground(g, new Rectangle(, , 0x10, 0x10));
}
else
{
ControlPaint.DrawSizeGrip(g, content.BackColor, , , 0x10, 0x10);
}
}
GraphicsState gs = e.Graphics.Save();
e.Graphics.ResetTransform();
if (resizableTop)
{
if (resizableLeft)
{
e.Graphics.RotateTransform();
e.Graphics.TranslateTransform(-clientSize.Width, -clientSize.Height);
}
else
{
e.Graphics.ScaleTransform(, -);
e.Graphics.TranslateTransform(, -clientSize.Height);
}
}
else if (resizableLeft)
{
e.Graphics.ScaleTransform(-, );
e.Graphics.TranslateTransform(-clientSize.Width, );
}
e.Graphics.DrawImage(gripImage, clientSize.Width - 0x10, clientSize.Height - 0x10 + , 0x10, 0x10);
e.Graphics.Restore(gs);
}
} #endregion
}
}

然后新建一个自定义控件,代码如下


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.Collections;
using System.Reflection;
using Newtonsoft.Json.Linq; namespace Controls
{ /// <summary>
/// 功能描述:自定义多选下拉框
/// 作  者:huangzh
/// 创建日期:2016-01-04 11:57:13
/// 任务编号:
/// </summary>
public class ComboBoxEx : ComboBox
{
PopupForm frmhost;
TreeView lst = new TreeView();
/// <summary>
/// 功能描述:构造方法
/// 作  者:huangzh
/// 创建日期:2016-01-04 11:57:27
/// 任务编号:
/// </summary>
public ComboBoxEx()
{
this.DrawMode = DrawMode.OwnerDrawFixed;//只有设置这个属性为OwnerDrawFixed才可能让重画起作用 lst.Width = ListWidth == ? this.Width : ListWidth;
lst.Height = ListHeight == ? : ListHeight;
lst.CheckBoxes = true;
lst.ShowLines = false;
lst.ShowPlusMinus = false;
lst.ShowRootLines = false;
lst.KeyUp += new KeyEventHandler(lst_KeyUp);
lst.AfterCheck += new TreeViewEventHandler(lst_AfterCheck);
this.DropDownHeight = ;
frmhost = new PopupForm(lst);
//frmhost.Closed += new ToolStripDropDownClosedEventHandler(frmhost_Closed);
//frmhost.Opened += new EventHandler(frmhost_Opened);
} void lst_KeyUp(object sender, KeyEventArgs e)
{
OnKeyUp(e);
} void lst_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Node.Checked)
{
if (Text != "")
{
Text += ",";
}
Text += e.Node.Tag.ToString();
}
else
{
string strValue = e.Node.Tag.ToString().Trim();
if (Text != "")
{
List<string> strs = Text.Split(',').ToList();
strs.Remove("");
if (strs.Contains(strValue))
{
strs.Remove(strValue);
Text = string.Join(",", strs);
}
}
}
} void frmhost_Opened(object sender, EventArgs e)
{ } void frmhost_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{ } #region Property
/// <summary>
/// 选中项
/// </summary>
[Description("选定项的值"), Category("Data")]
public List<TreeNode> SelectedItems
{
get
{
List<TreeNode> lsttn = new List<TreeNode>();
foreach (TreeNode tn in lst.Nodes)
{
if (tn.Checked)
{
lsttn.Add(tn);
}
}
return lsttn;
}
} /// <summary>
/// 数据源
/// </summary>
[Description("数据源"), Category("Data")]
public new object DataSource
{
get;
set;
}
/// <summary>
/// 显示字段
/// </summary>
[Description("显示字段"), Category("Data")]
public string DisplayFiled
{
get;
set;
}
/// <summary>
/// 值字段
/// </summary>
[Description("值字段"), Category("Data")]
public string ValueFiled
{
get;
set;
}
/// <summary>
/// 列表高度
/// </summary>
[Description("列表高度"), Category("Data")]
public int ListHeight
{
get;
set;
} /// <summary>
/// 列表宽度
/// </summary>
[Description("列表宽度"), Category("Data")]
public int ListWidth
{
get;
set;
}
#endregion /// <summary>
/// 功能描述:绑定数据
/// 作  者:huangzh
/// 创建日期:2016-01-04 10:38:51
/// 任务编号:
/// </summary>
public void DataBind()
{
this.BeginUpdate();
if (DataSource != null)
{
if (DataSource is IDataReader)
{
DataTable dataTable = new DataTable();
dataTable.Load(DataSource as IDataReader); DataBindToDataTable(dataTable);
}
else if (DataSource is DataView || DataSource is DataSet || DataSource is DataTable)
{
DataTable dataTable = null; if (DataSource is DataView)
{
dataTable = ((DataView)DataSource).ToTable();
}
else if (DataSource is DataSet)
{
dataTable = ((DataSet)DataSource).Tables[];
}
else
{
dataTable = ((DataTable)DataSource);
} DataBindToDataTable(dataTable);
}
else if (DataSource is IEnumerable)
{
DataBindToEnumerable((IEnumerable)DataSource);
}
else
{
throw new Exception("DataSource doesn't support data type: " + DataSource.GetType().ToString());
}
}
else
{
lst.Nodes.Clear();
} this.EndUpdate();
} /// <summary>
/// 功能描述:绑定Table数据
/// 作  者:huangzh
/// 创建日期:2016-01-04 10:47:27
/// 任务编号:
/// </summary>
/// <param name="dt">dt</param>
private void DataBindToDataTable(DataTable dt)
{
foreach (DataRow dr in dt.Rows)
{
TreeNode tn = new TreeNode();
if (!string.IsNullOrEmpty(DisplayFiled) && !string.IsNullOrEmpty(ValueFiled))
{
tn.Text = dr[DisplayFiled].ToString();
tn.Tag = dr[ValueFiled].ToString();
}
else if (string.IsNullOrEmpty(ValueFiled))
{
tn.Text = dr[DisplayFiled].ToString();
tn.Tag = dr[DisplayFiled].ToString();
}
else if (string.IsNullOrEmpty(DisplayFiled))
{
tn.Text = dr[ValueFiled].ToString();
tn.Tag = dr[ValueFiled].ToString();
}
else
{
throw new Exception("ValueFiled和DisplayFiled至少保证有一项有值");
}
tn.ToolTipText = tn.Text; tn.Checked = false;
lst.Nodes.Add(tn);
}
} /// <summary>
/// 绑定到可枚举类型
/// </summary>
/// <param name="enumerable">可枚举类型</param>
private void DataBindToEnumerable(IEnumerable enumerable)
{
IEnumerator enumerator = enumerable.GetEnumerator();
while (enumerator.MoveNext())
{
object currentObject = enumerator.Current;
lst.Nodes.Add(CreateListItem(currentObject));
}
} /// <summary>
/// 功能描述:获取一个CheckBox
/// 作  者:huangzh
/// 创建日期:2016-01-04 10:53:12
/// 任务编号:
/// </summary>
/// <param name="obj">obj</param>
/// <returns>返回值</returns>
private TreeNode CreateListItem(Object obj)
{
TreeNode item = new TreeNode(); if (obj is string)
{
item.Text = obj.ToString();
item.Tag = obj.ToString();
}
else
{
if (DisplayFiled != "")
{
item.Text = GetPropertyValue(obj, DisplayFiled);
}
else
{
item.Text = obj.ToString();
} if (ValueFiled != "")
{
item.Tag = GetPropertyValue(obj, ValueFiled);
}
else
{
item.Tag = obj.ToString();
}
}
item.ToolTipText = item.Text;
return item;
} /// <summary>
/// 取得属性值
/// </summary>
/// <param name="obj"></param>
/// <param name="propertyName"></param>
private string GetPropertyValue(object obj, string propertyName)
{
object result = null; result = ObjectUtil.GetPropertyValue(obj, propertyName);
return result == null ? String.Empty : result.ToString();
} #region override /// <summary>
/// 功能描述:OnKeyUp
/// 作  者:huangzh
/// 创建日期:2016-01-04 11:58:33
/// 任务编号:
/// </summary>
/// <param name="e">e</param>
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyDown(e);
bool Pressed = (e.Control && ((e.KeyData & Keys.A) == Keys.A));
if (Pressed)
{
this.Text = "";
for (int i = ; i < lst.Nodes.Count; i++)
{
lst.Nodes[i].Checked = true;
}
}
} /// <summary>
/// 功能描述:OnDropDown
/// 作  者:huangzh
/// 创建日期:2016-01-04 11:58:53
/// 任务编号:
/// </summary>
/// <param name="e">e</param>
protected override void OnDropDown(EventArgs e)
{
this.DroppedDown = false;
string strValue = this.Text;
if (!string.IsNullOrEmpty(strValue))
{
List<string> lstvalues = strValue.Split(',').ToList<string>();
foreach (TreeNode tn in lst.Nodes)
{
if (tn.Checked && !lstvalues.Contains(tn.Tag.ToString()) && !string.IsNullOrEmpty(tn.Tag.ToString().Trim()))
{
tn.Checked = false;
}
else if (!tn.Checked && lstvalues.Contains(tn.Tag.ToString()) && !string.IsNullOrEmpty(tn.Tag.ToString().Trim()))
{
tn.Checked = true;
}
}
}
else
{
foreach (TreeNode tn in lst.Nodes)
{
tn.Checked = false;
}
}
frmhost.Show(this);
}
#endregion
} /// <summary>
/// 对象帮助类
/// </summary>
public class ObjectUtil
{
/// <summary>
/// 获取对象的属性值
/// </summary>
/// <param name="obj">可能是DataRowView或一个对象</param>
/// <param name="propertyName">属性名</param>
/// <returns>属性值</returns>
public static object GetPropertyValue(object obj, string propertyName)
{
object result = null; try
{
if (obj is DataRow)
{
result = (obj as DataRow)[propertyName];
}
else if (obj is DataRowView)
{
result = (obj as DataRowView)[propertyName];
}
else if (obj is JObject)
{
result = (obj as JObject).Value<JValue>(propertyName).Value; //.getValue(propertyName);
}
else
{
result = GetPropertyValueFormObject(obj, propertyName);
}
}
catch (Exception)
{
// 找不到此属性
} return result;
} /// <summary>
/// 获取对象的属性值
/// </summary>
/// <param name="obj">对象</param>
/// <param name="propertyName">属性名("Color"、"BodyStyle"或者"Info.UserName")</param>
/// <returns>属性值</returns>
private static object GetPropertyValueFormObject(object obj, string propertyName)
{
object rowObj = obj;
object result = null; if (propertyName.IndexOf(".") > )
{
string[] properties = propertyName.Split('.');
object tmpObj = rowObj; for (int i = ; i < properties.Length; i++)
{
PropertyInfo property = tmpObj.GetType().GetProperty(properties[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null)
{
tmpObj = property.GetValue(tmpObj, null);
}
} result = tmpObj;
}
else
{
PropertyInfo property = rowObj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null)
{
result = property.GetValue(rowObj, null);
}
} return result;
}
}
}

然后就是使用了,直接拖一个到界面上,然后设置值就可以了

ListHeight,ListWidth 这两个属性一定要修改下的哦

然后就是绑定数据源

  var varSourceFrom = from p in lstEnumEnitty
where p.Type == "source"
select p;
cboSourceFromType.DataSource = varSourceFrom;
cboSourceFromType.DisplayFiled = "Name";
cboSourceFromType.ValueFiled = "Code";
cboSourceFromType.DataBind();

效果就是这样的了

需要引用的一个DLL去我的上一个文章里面下载吧

c# 自定义多选下拉列表2的更多相关文章

  1. Flex4 双选下拉列表的实现(源代码)

    本文属原创文章,如需转载,请注明出处,谢谢 企业应用中少不了双选下拉列表控件,但几乎都没有独立的控件,Flex在这上面得天独厚,ArrayCollection的过滤功能使得我们只需要一个数据源就可以将 ...

  2. WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...

  3. 一款不错的多选下拉列表利器—— Ext.ux.form.SuperBoxSelect

    在B/S系统中,下拉列表(select/dropdownlist/combobox)的应用随处可见,为了增强用户体验,开发人员也常常会做一些带联想功能的下拉列表, 特别是数据项比较多的时候,用户筛选起 ...

  4. 【转】WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 下拉选择控件ComboBox的自定义样式及扩展: 自定义多选控件Mul ...

  5. WPF 自定义ComboBox样式,自定义多选控件

    原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...

  6. 自定义SWT控件二之自定义多选下拉框

    2.自定义下拉多选框 package com.view.control.select; import java.util.ArrayList; import java.util.HashMap; im ...

  7. javascript操作多选下拉列表

    闲来无事,把javascript操作多选下拉列表有关的操作知识复习了一遍,代码附上 <%-- Created by IntelliJ IDEA. User: Administrator Date ...

  8. kendoUI 多选下拉列表 kendoMultiSelect

    问题1:被重复渲染 点击新增按钮----弹出模态框 多选下拉列表在多选框中只是初始化过一次.但是每次点击新增后  发现 多选下拉列表 被重复渲染了 解决方案 在 新增时  先将其父元素div中  的s ...

  9. 如何对tableview进行自定义多选

    前言: 很多入门不久的程序员或许都会遇到系统自带的tableview多选时cell选择时不能选择自己想要的点击时的颜色或者图片,这让初级开发者们很烦恼.今天,我试着花了几个小时的时间用了自己的想法,去 ...

随机推荐

  1. hdu 5066 Harry And Physical Teacher(Bestcoder Round #14)

    Harry And Physical Teacher Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  2. Petroglyph访问:中间件游戏

    Xsolla有幸与Petroglyph的总裁及创始人Michael Legg进行了对话. 这是及时战略游戏中对主要一家公司. 由前Westwood的员工 创办,还设计了一块新的RTS游戏-Grey G ...

  3. 多线程——@synchronized(object)

    @synchronized 的作用是创建一个相互排斥锁,保证此时没有其他线程对self对象进行改动.这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其他线程訪问,起到线程的保 ...

  4. 点击鼠标获取元素ID

    原文:点击鼠标获取元素ID public partial class Form1 : Form { public Form1() { InitializeComponent(); } private ...

  5. cscope的使用

    转自:http://easwy.com/blog/archives/advanced-vim-skills-cscope/ 本节所用命令的帮助入口: :help cscope 在前面的文章中介绍了利用 ...

  6. 关于Cassandra与Thrift在int/text/varint上的暧昧

    近期简单写了一个基于Cassandra/C++的日志缓存,虽然是Nosql,但是在实际应用中,还是期望能有部分的临时CQL统计 或+-*/可以支持 所以在针对部分字段入库时,选择了作为整形录入,于是麻 ...

  7. 四大OLAP工具选型浅析

    OLAP(在线分析处理)这个名词是在1993年由E.F.Codd提出来的,只是,眼下市场上的主流产品差点儿都是在1993年之前就已出来,有的甚至已有三十多年的历史了.OLAP产品不少,本文将主要涉及C ...

  8. css3中display和box小结

    display:table用处: 1.创建登高列 2.实现大小不确定元素的垂直居中 3.容器内子项目数目未知,子项目平均分配容器的水平空间 float必须指定其宽度才行,不确定的话就用display: ...

  9. Thrift实现C#通讯服务程序

    Thrift初探:简单实现C#通讯服务程序 好久没有写文章了,由于换工作了,所以一直没有时间来写博.今天抽个空练练手下~最近接触了下Thrift,网上也有很多文章对于Thrift做了说明:       ...

  10. JAVA学习课第五十三届 — IO流程(七)File打靶 &amp; Properties设置

    一个.锻炼 深度遍历目录 深度遍历非常自然而然想到递归,而递归就非常自然的想到事实上现的底层算法是栈 对指定文件夹下列出全部内容(包括子文件夹的内容) PS:建议不要遍历C盘 import java. ...