* UICheckBoxGroup: 重写UICheckBoxGroup

This commit is contained in:
Sunny 2023-11-07 23:19:23 +08:00
parent 718560e5c4
commit 0c1b7d13ba
2 changed files with 119 additions and 120 deletions

View File

@ -52,7 +52,7 @@ namespace Sunny.UI
Size = new Size(150, 29); Size = new Size(150, 29);
SetStyle(ControlStyles.StandardDoubleClick, UseDoubleClick); SetStyle(ControlStyles.StandardDoubleClick, UseDoubleClick);
foreColor = UIStyles.Blue.CheckBoxForeColor; ForeColor = UIStyles.Blue.CheckBoxForeColor;
fillColor = UIStyles.Blue.CheckBoxColor; fillColor = UIStyles.Blue.CheckBoxColor;
} }
@ -126,7 +126,7 @@ namespace Sunny.UI
set set
{ {
_imageSize = Math.Max(value, 16); _imageSize = Math.Max(value, 16);
_imageSize = Math.Min(value, 128); _imageSize = Math.Min(value, 64);
Invalidate(); Invalidate();
} }
} }
@ -138,17 +138,6 @@ namespace Sunny.UI
[Description("是否只读"), Category("SunnyUI")] [Description("是否只读"), Category("SunnyUI")]
public bool ReadOnly { get; set; } public bool ReadOnly { get; set; }
/// <summary>
/// 字体颜色
/// </summary>
[Description("字体颜色"), Category("SunnyUI")]
[DefaultValue(typeof(Color), "48, 48, 48")]
public override Color ForeColor
{
get => foreColor;
set => SetForeColor(value);
}
/// <summary> /// <summary>
/// 图标与文字之间间隔 /// 图标与文字之间间隔
/// </summary> /// </summary>
@ -200,7 +189,7 @@ namespace Sunny.UI
protected override void OnPaintFore(Graphics g, GraphicsPath path) protected override void OnPaintFore(Graphics g, GraphicsPath path)
{ {
//填充文字 //填充文字
Color color = foreColor; Color color = ForeColor;
color = Enabled ? color : UIDisableColor.Fore; color = Enabled ? color : UIDisableColor.Fore;
Rectangle rect = new Rectangle(_imageSize + _imageInterval * 2, 0, Width - _imageSize + _imageInterval * 2, Height); Rectangle rect = new Rectangle(_imageSize + _imageInterval * 2, 0, Width - _imageSize + _imageInterval * 2, Height);
g.DrawString(Text, Font, color, rect, ContentAlignment.MiddleLeft); g.DrawString(Text, Font, color, rect, ContentAlignment.MiddleLeft);
@ -263,7 +252,7 @@ namespace Sunny.UI
{ {
base.SetStyleColor(uiColor); base.SetStyleColor(uiColor);
fillColor = uiColor.CheckBoxColor; fillColor = uiColor.CheckBoxColor;
foreColor = uiColor.CheckBoxForeColor; ForeColor = uiColor.CheckBoxForeColor;
} }
/// <summary> /// <summary>

View File

@ -24,6 +24,7 @@
* 2022-11-21: V3.2.9 * 2022-11-21: V3.2.9
* 2023-04-19: V3.3.5 ForeColor * 2023-04-19: V3.3.5 ForeColor
* 2023-06-27: V3.3.9 Tag改为TagString * 2023-06-27: V3.3.9 Tag改为TagString
* 2023-11-07: V3.5.2 UICheckBoxGroup
******************************************************************************/ ******************************************************************************/
using System; using System;
@ -62,20 +63,11 @@ namespace Sunny.UI
public UICheckBoxGroup() public UICheckBoxGroup()
{ {
items.CountChange += Items_CountChange; items.CountChange += Items_CountChange;
ForeColor = UIStyles.Blue.CheckBoxForeColor;
checkBoxColor = UIStyles.Blue.CheckBoxColor;
} }
protected override void OnFontChanged(EventArgs e) private Color checkBoxColor;
{
base.OnFontChanged(e);
if (DefaultFontSize < 0)
{
foreach (var item in boxes)
{
item.Font = Font;
}
}
}
private void Items_CountChange(object sender, EventArgs e) private void Items_CountChange(object sender, EventArgs e)
{ {
@ -90,26 +82,29 @@ namespace Sunny.UI
public bool this[int index] public bool this[int index]
{ {
get => GetItemCheckState(index); get => GetItemCheckState(index);
set => SetItemCheckState(index, value); set
}
/// <summary>
/// 析构事件
/// </summary>
~UICheckBoxGroup()
{
ClearBoxes();
}
private void ClearBoxes()
{
foreach (var box in boxes)
{ {
box.Hide(); SetItemCheckState(index, value);
box.Dispose(); Invalidate();
} }
}
boxes.Clear(); private Dictionary<int, bool> CheckStates = new Dictionary<int, bool>();
private Dictionary<int, Rectangle> CheckBoxRects = new Dictionary<int, Rectangle>();
private int _imageSize = 16;
[DefaultValue(16)]
[Description("图标大小"), Category("SunnyUI")]
[Browsable(false)]
public int CheckBoxSize
{
get => _imageSize;
set
{
_imageSize = Math.Max(value, 16);
_imageSize = Math.Min(value, 64);
Invalidate();
}
} }
/// <summary> /// <summary>
@ -118,7 +113,8 @@ namespace Sunny.UI
public void Clear() public void Clear()
{ {
Items.Clear(); Items.Clear();
ClearBoxes(); CheckStates.Clear();
CheckBoxRects.Clear();
Invalidate(); Invalidate();
} }
@ -134,36 +130,29 @@ namespace Sunny.UI
private readonly UIObjectCollection items = new UIObjectCollection(); private readonly UIObjectCollection items = new UIObjectCollection();
private void CreateBoxes() /// <summary>
/// 设置主题样式
/// </summary>
/// <param name="uiColor">主题样式</param>
public override void SetStyleColor(UIBaseStyle uiColor)
{ {
if (Items.Count != boxes.Count) base.SetStyleColor(uiColor);
{ checkBoxColor = uiColor.CheckBoxColor;
ClearBoxes(); ForeColor = uiColor.CheckBoxForeColor;
for (int i = 0; i < Items.Count; i++)
{
UICheckBox box = new UICheckBox();
box.BackColor = Color.Transparent;
box.Font = Font;
box.Parent = this;
box.TagString = i.ToString();
box.Style = Style;
//box.IsScaled = IsScaled;
box.ValueChanged += Box_ValueChanged;
box.Text = Items[i]?.ToString();
box.StyleCustomMode = StyleCustomMode;
box.ForeColor = ForeColor;
boxes.Add(box);
}
}
} }
protected override void AfterSetForeColor(Color color) /// <summary>
/// 填充颜色,当值为背景色或透明色或空值则不填充
/// </summary>
[Description("填充颜色"), Category("SunnyUI")]
[DefaultValue(typeof(Color), "80, 160, 255")]
public Color CheckBoxColor
{ {
base.AfterSetForeColor(color); get => checkBoxColor;
foreach (var item in boxes) set
{ {
item.ForeColor = color; checkBoxColor = value;
Invalidate();
} }
} }
@ -174,33 +163,66 @@ namespace Sunny.UI
protected override void OnPaint(PaintEventArgs e) protected override void OnPaint(PaintEventArgs e)
{ {
base.OnPaint(e); base.OnPaint(e);
CreateBoxes();
if (Items.Count == 0) return; if (Items.Count == 0) return;
int startX = StartPos.X; int startX = StartPos.X;
int startY = TitleTop + StartPos.Y; int startY = TitleTop + StartPos.Y;
for (int i = 0; i < Items.Count; i++) for (int i = 0; i < Items.Count; i++)
{ {
boxes[i].Text = Items[i].ToString(); string text = Items[i].ToString();
int rowIndex = i / ColumnCount; int rowIndex = i / ColumnCount;
int columnIndex = i % ColumnCount; int columnIndex = i % ColumnCount;
int left = startX + ItemSize.Width * columnIndex + ColumnInterval * columnIndex;
int top = startY + ItemSize.Height * rowIndex + RowInterval * rowIndex;
Rectangle rect = new Rectangle(left, top, ItemSize.Width, ItemSize.Height);
int ImageSize = CheckBoxSize;
boxes[i].Left = startX + ItemSize.Width * columnIndex + ColumnInterval * columnIndex; //图标
boxes[i].Top = startY + ItemSize.Height * rowIndex + RowInterval * rowIndex; top = rect.Top + (rect.Height - ImageSize) / 2;
boxes[i].Size = ItemSize; Color color = Enabled ? checkBoxColor : foreDisableColor;
boxes[i].Show();
if (this[i])
{
e.Graphics.FillRoundRectangle(color, new Rectangle((int)left, (int)top, ImageSize, ImageSize), 1);
color = BackColor.IsValid() ? BackColor : Color.White;
Point pt2 = new Point((int)(left + ImageSize * 2 / 5.0f), (int)(top + ImageSize * 3 / 4.0f) - (ImageSize.Div(10)));
Point pt1 = new Point((int)left + 2 + ImageSize.Div(10), pt2.Y - (pt2.X - 2 - ImageSize.Div(10) - (int)left));
Point pt3 = new Point((int)left + ImageSize - 2 - ImageSize.Div(10), pt2.Y - (ImageSize - pt2.X - 2 - ImageSize.Div(10)) - (int)left);
PointF[] CheckMarkLine = { pt1, pt2, pt3 };
using Pen pn = new Pen(color, 2);
e.Graphics.SetHighQuality();
e.Graphics.DrawLines(pn, CheckMarkLine);
e.Graphics.SetDefaultQuality();
}
else
{
using Pen pn = new Pen(color, 1);
e.Graphics.DrawRoundRectangle(pn, new Rectangle((int)left + 1, (int)top + 1, ImageSize - 2, ImageSize - 2), 1);
e.Graphics.DrawRectangle(pn, new Rectangle((int)left + 2, (int)top + 2, ImageSize - 4, ImageSize - 4));
}
e.Graphics.DrawString(text, Font, ForeColor, rect, ContentAlignment.MiddleLeft, ImageSize + 4, 0);
if (CheckBoxRects.NotContainsKey(i))
CheckBoxRects.Add(i, rect);
else
CheckBoxRects[i] = rect;
} }
} }
private void Box_ValueChanged(object sender, bool value) protected override void OnMouseClick(MouseEventArgs e)
{ {
UICheckBox checkBox = (UICheckBox)sender; base.OnMouseClick(e);
if (!multiChange) foreach (var pair in CheckBoxRects)
{ {
ValueChanged?.Invoke(this, checkBox.TagString.ToInt(), checkBox.Text, checkBox.Checked); if (e.Location.InRect(pair.Value) && pair.Key >= 0 && pair.Key < items.Count)
{
this[pair.Key] = !this[pair.Key];
ValueChanged?.Invoke(this, pair.Key, Items[pair.Key].ToString(), this[pair.Key]);
Invalidate();
}
} }
} }
@ -213,29 +235,24 @@ namespace Sunny.UI
get get
{ {
List<int> indexes = new List<int>(); List<int> indexes = new List<int>();
for (int i = 0; i < Items.Count; i++)
for (int i = 0; i < boxes.Count; i++)
{ {
if (boxes[i].Checked) if (this[i]) indexes.Add(i);
indexes.Add(i);
} }
return indexes; return indexes;
} }
set set
{ {
if (boxes.Count != Items.Count)
{
CreateBoxes();
}
foreach (int i in value) foreach (int i in value)
{ {
if (i >= 0 && i < boxes.Count) if (i >= 0 && i < Items.Count)
{ {
boxes[i].Checked = true; SetItemCheckState(i, true);
} }
} }
Invalidate();
} }
} }
@ -246,11 +263,12 @@ namespace Sunny.UI
/// <param name="isChecked">是否选中</param> /// <param name="isChecked">是否选中</param>
public void SetItemCheckState(int index, bool isChecked) public void SetItemCheckState(int index, bool isChecked)
{ {
CreateBoxes(); if (index >= 0 && index < Items.Count && CheckStates.NotContainsKey(index))
if (index >= 0 && index < boxes.Count)
{ {
boxes[index].Checked = isChecked; CheckStates.Add(index, isChecked);
} }
CheckStates[index] = isChecked;
} }
/// <summary> /// <summary>
@ -260,8 +278,8 @@ namespace Sunny.UI
/// <returns>是否选中</returns> /// <returns>是否选中</returns>
public bool GetItemCheckState(int index) public bool GetItemCheckState(int index)
{ {
if (index >= 0 && index < items.Count) if (index >= 0 && index < items.Count && CheckStates.ContainsKey(index))
return boxes[index].Checked; return CheckStates[index];
return false; return false;
} }
@ -276,18 +294,15 @@ namespace Sunny.UI
{ {
List<object> objects = new List<object>(); List<object> objects = new List<object>();
for (int i = 0; i < boxes.Count; i++) for (int i = 0; i < Items.Count; i++)
{ {
if (boxes[i].Checked) if (this[i]) objects.Add(Items[i]);
objects.Add(Items[i]);
} }
return objects; return objects;
} }
} }
private readonly List<UICheckBox> boxes = new List<UICheckBox>();
private int columnCount = 1; private int columnCount = 1;
/// <summary> /// <summary>
@ -340,12 +355,12 @@ namespace Sunny.UI
} }
private int columnInterval; private int columnInterval = 6;
/// <summary> /// <summary>
/// 显示项列之间的间隔 /// 显示项列之间的间隔
/// </summary> /// </summary>
[DefaultValue(0)] [DefaultValue(6)]
[Description("显示项列之间的间隔"), Category("SunnyUI")] [Description("显示项列之间的间隔"), Category("SunnyUI")]
public int ColumnInterval public int ColumnInterval
{ {
@ -379,13 +394,12 @@ namespace Sunny.UI
/// </summary> /// </summary>
public void SelectAll() public void SelectAll()
{ {
multiChange = true; for (int i = 0; i < Items.Count; i++)
foreach (var box in boxes)
{ {
box.Checked = true; SetItemCheckState(i, true);
} }
multiChange = false; Invalidate();
} }
/// <summary> /// <summary>
@ -393,13 +407,12 @@ namespace Sunny.UI
/// </summary> /// </summary>
public void UnSelectAll() public void UnSelectAll()
{ {
multiChange = true; for (int i = 0; i < Items.Count; i++)
foreach (var box in boxes)
{ {
box.Checked = false; SetItemCheckState(i, false);
} }
multiChange = false; Invalidate();
} }
/// <summary> /// <summary>
@ -407,15 +420,12 @@ namespace Sunny.UI
/// </summary> /// </summary>
public void ReverseSelected() public void ReverseSelected()
{ {
multiChange = true; for (int i = 0; i < Items.Count; i++)
foreach (var box in boxes)
{ {
box.Checked = !box.Checked; SetItemCheckState(i, !this[i]);
} }
multiChange = false; Invalidate();
} }
private bool multiChange;
} }
} }