今天给大家上个硬货,下拉多选框,同时也是下拉多选树,支持父节点跟子节点!该控件是基于Telerik控件封装实现的,所以大家在使用的过程中需要引用Telerik.WinControls.dll、Telerik.WinControls.UI.dll,还有一些相关的类库,大家有需要的可以去网上自己找,另外我也会把一些动态库放到CSDN上面,大家需要可以去下载。
[ToolboxItem(true)]
public partial class DropDownTreeViewControl : RadControl
{
public DropDownTreeViewElement TreeViewElement { get; private set; }
public RadTreeView TreeViewControl
{
get
{
return this.TreeViewElement.TreeViewControl;
}
}
protected override void CreateChildItems(RadElement parent)
{
this.AllowShowFocusCues = true;
base.CreateChildItems(parent);
this.TreeViewElement = new DropDownTreeViewElement();
parent.Children.Add(TreeViewElement);
}
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
this.TreeViewElement.Focus();
}
protected override void OnBindingContextChanged(EventArgs e)
{
base.OnBindingContextChanged(e);
this.TreeViewControl.BindingContext = this.BindingContext;
}
public class DropDownTreeViewElement : LightVisualElement
{
private readonly Color BG_COLOR = Color.White;
private readonly Color BORDER_COLOR = Color.LightBlue;
private readonly Color ARROW_BORDER_COLOR = Color.LightGray;
private readonly Color ARROW_NORMAL_BG_COLOR = Color.White;
private readonly Color ARROW_MOUSE_OVER_BG_COLOR = Color.LightYellow;
private readonly Color ARROW_PRESSED_BG_COLOR = Color.DarkOrange;
private readonly int NORMAL_BORDER_WIDTH = 1;
private readonly int FOCUS_BORDER_WIDTH = 2;
private RadArrowButtonElement arrow;
private PopupForm popup;
private bool isInnerCallHide;
public bool IsPopupOpen { get; private set; }
public RadTreeView TreeViewControl
{
get
{
return this.popup.TreeView;
}
}
protected override void InitializeFields()
{
base.InitializeFields();
// style
this.DrawBorder = true;
this.BorderBoxStyle = BorderBoxStyle.SingleBorder;
this.BorderGradientStyle = GradientStyles.Solid;
this.BorderColor = BORDER_COLOR;
this.DrawFill = true;
this.NumberOfColors = 1;
this.GradientStyle = GradientStyles.Solid;
this.BackColor = BG_COLOR;
this.StretchHorizontally = true;
this.StretchVertically = true;
}
protected override void CreateChildElements()
{
base.CreateChildElements();
// arrow
this.CreateArrow();
// popup
this.CreatePopup();
this.Children.Add(arrow);
}
private void CreatePopup()
{
this.popup = new PopupForm(this);
this.popup.PopupClosing += Popup_PopupClosing;
this.popup.PopupClosed += Popup_PopupClosed;
}
private void Popup_PopupClosing(object sender, RadPopupClosingEventArgs args)
{
// mouse postion in control-bounds prevent
if (args.CloseReason == RadPopupCloseReason.Mouse)
{
var boundsSc = RectangleToScreen(this.Bounds);
if (boundsSc.Contains(MousePosition))
{
args.Cancel = true;
}
}
}
private void Popup_PopupClosed(object sender, RadPopupClosedEventArgs args)
{
if (isInnerCallHide)
{
return;
}
this.IsPopupOpen = false;
this.SwitchArrowState(false);
}
private void CreateArrow()
{
this.arrow = new RadArrowButtonElement()
{
ClickMode = ClickMode.Press,
MinSize = new Size(SystemInformation.VerticalScrollBarWidth,
RadArrowButtonElement.RadArrowButtonDefaultSize.Height),
StretchHorizontally = false,
StretchVertically = true,
Margin = new System.Windows.Forms.Padding(2),
};
arrow.Fill.NumberOfColors = 1;
arrow.Fill.BackColor = ARROW_NORMAL_BG_COLOR;
arrow.Border.BoxStyle = BorderBoxStyle.SingleBorder;
arrow.Border.GradientStyle = GradientStyles.Solid;
arrow.Border.ForeColor = ARROW_BORDER_COLOR;
arrow.RadPropertyChanged += Arrow_RadPropertyChanged;
arrow.Click += Arrow_Click;
}
private void Arrow_Click(object sender, EventArgs e)
{
if (this.IsPopupOpen)
{
this.IsPopupOpen = false;
this.SwitchArrowState(false);
this.HidePopup();
}
else
{
this.IsPopupOpen = true;
this.SwitchArrowState(true);
this.ShowPopup();
}
}
private void HidePopup()
{
this.isInnerCallHide = true;
this.popup.Hide();
this.isInnerCallHide = false;
}
private void ShowPopup()
{
this.popup.Width = this.Bounds.Width;
this.popup.Height = 250;
this.popup.ShowPopup(this.RectangleToScreen(this.ControlBoundingRectangle));
}
private void SwitchArrowState(bool isPressed)
{
this.arrow.Fill.BackColor = isPressed ? ARROW_PRESSED_BG_COLOR :
(arrow.IsMouseOver ? ARROW_MOUSE_OVER_BG_COLOR : ARROW_NORMAL_BG_COLOR);
}
protected override void OnPropertyChanged(RadPropertyChangedEventArgs e)
{
if (e.Property == ContainsFocusProperty)
{
var isFocus = (bool)e.NewValue;
this.BorderWidth = isFocus ? FOCUS_BORDER_WIDTH : NORMAL_BORDER_WIDTH;
}
base.OnPropertyChanged(e);
}
protected override SizeF ArrangeOverride(SizeF finalSize)
{
base.ArrangeOverride(finalSize);
// arrow on right side
float width = this.arrow.DesiredSize.Width;
float x = this.RightToLeft ? 0f : (finalSize.Width - width);
RectangleF finalRect = new RectangleF(x, 0f, width, finalSize.Height);
this.arrow.Arrange(finalRect);
return finalSize;
}
private void Arrow_RadPropertyChanged(object sender, RadPropertyChangedEventArgs e)
{
if (e.Property == RadArrowButtonElement.IsMouseOverProperty)
{
if (this.IsPopupOpen)
{
return;
}
var arrow = sender as RadArrowButtonElement;
var isMouseOver = (bool)e.NewValue;
arrow.Fill.BackColor = isMouseOver ? ARROW_MOUSE_OVER_BG_COLOR : ARROW_NORMAL_BG_COLOR;
}
}
}
public class PopupForm : RadSizablePopupControl
{
private HostTreeView tv;
public PopupForm(RadItem owner)
: base(owner)
{
this.SizingMode = SizingMode.UpDownAndRightBottom;
this.VerticalAlignmentCorrectionMode = AlignmentCorrectionMode.SnapToOuterEdges;
}
public RadTreeView TreeView
{
get
{
return this.tv.TreeView;
}
}
protected override void CreateChildItems(RadElement parent)
{
base.CreateChildItems(parent);
this.tv = new HostTreeView();
this.tv.TreeView.Focusable = false;
this.tv.TreeView.CheckBoxes = true;
this.SizingGripDockLayout.Children.Add(tv);
}
public override bool OnMouseWheel(Control target, int delta)
{
if (delta < 0)
{
this.tv.TreeView.VScrollBar.PerformSmallIncrement(1);
}
else
{
this.tv.TreeView.VScrollBar.PerformSmallDecrement(1);
}
return true;
}
}
public class HostTreeView : Telerik.WinControls.RadHostItem
{
public HostTreeView()
: base(new RadTreeView())
{
}
public RadTreeView TreeView
{
get
{
return this.HostedControl as RadTreeView;
}
}
}
}
最后说明一点吧,这次封装对于我自己来说还有一个不满意的地方,那就是选择一些项目以后,界面上不显示已经选择的项,希望有人能够完善一下,给出改造后的代码。