tangxu
2025-01-13 4f7cb65b079d88d5a829688b24d26d5145c5df47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace DPumpHydr.WinFrmUI.WenSkin.Controls
{
    public class WenListBox : ListBox
    {
        public WenListBox()
        {
            base.SetStyle(
                //ControlStyles.UserPaint |
                ControlStyles.DoubleBuffer |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor, true);
            base.UpdateStyles();
            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.IntegralHeight = false;
            ItemHeight = 23;
        }
 
        #region 委托事件
 
        [Category("Wen"), Description("项被点击事件")]
        public event WenListBoxEventHandler ItemClick;
 
        #endregion
 
        #region 私有属性
 
        //选中项改变之前的选中项索引
        private int selectBefore = -1;
 
        private int MouseItemIndex;
        private bool line = true;
        private bool radioBox = true;
        private Color oneRowColor = Color.DeepSkyBlue;
        private Color towRowColor = Color.Aquamarine;
        private Color selectedRowColor = Color.DarkCyan;
        private Color mouseMoveRowColor = Color.Cyan;
        private int itemHeight;
 
        #endregion
 
        #region 公有属性
 
        [Category("Wen"), Description("是否增加序号"), DefaultValue(true)]
        public bool Line { get => line; set { line = value; this.Invalidate(); } }
 
        [Category("Wen"), Description("是否增加选框"), DefaultValue(true)]
        public bool RadioBox { get => radioBox; set { radioBox = value; this.Invalidate(); } }
 
        [Category("Wen"), Description("奇数行颜色"), DefaultValue(typeof(Color), "DeepSkyBlue")]
        public Color OneRowColor { get => oneRowColor; set { oneRowColor = value; this.Invalidate(); } }
 
        [Category("Wen"), Description("偶数行颜色"), DefaultValue(typeof(Color), "Aquamarine")]
        public Color TowRowColor { get => towRowColor; set { towRowColor = value; this.Invalidate(); } }
 
        [Category("Wen"), Description("选中颜色"), DefaultValue(typeof(Color), "DarkCyan")]
        public Color SelectedRowColor { get => selectedRowColor; set { selectedRowColor = value; this.Invalidate(); } }
 
        [Category("Wen"), Description("鼠标移动行颜色"), DefaultValue(typeof(Color), "Cyan")]
        public Color MouseMoveRowColor { get => mouseMoveRowColor; set { mouseMoveRowColor = value; this.Invalidate(); } }
 
        #endregion
 
        #region 数据绑定
        [Category("WenData"), Description("绑定数据列"), DefaultValue(null)]
        public string ColumnName { get; set; }
        private object dataSource { get; set; }
        [Browsable(false)]
        public new object DataSource
        {
            get => dataSource;
            set
            {
                if (value != null)
                {
                    dataSource = value;
                    DataBind();
                }
            }
        }
        private void DataBind()
        {
            if (dataSource == null)
                return;
            this.Items.Clear();
 
            //分类数据绑定
            switch (dataSource)
            {
                case DataSet ds:
                    DataBindDataTable(ds.Tables[0]);
                    break;
                case DataTable dt:
                    DataBindDataTable(dt);
                    break;
                case IList ilist:
                    if (string.IsNullOrWhiteSpace(ColumnName))
                    {
                        foreach (var li in ilist)
                        {
                            List<System.Reflection.PropertyInfo> propertyInfos = new List<System.Reflection.PropertyInfo>(li.GetType().GetProperties());
                            string value = propertyInfos.Find(a => a.Name.ToUpper() == ColumnName.ToUpper())?.GetValue(li, null)?.ToString();
                            Items.Add(value);
                        }
                    }
                    else
                    {
                        foreach (var li in ilist)
                        {
                            string value = li.GetType().GetProperties()[0].GetValue(li, null)?.ToString();
                            Items.Add(value);
                        }
                    }
                    break;
                default:
                    break;
            }
 
            //绑定数据   
            void DataBindDataTable(DataTable dt)
            {
                if (string.IsNullOrWhiteSpace(ColumnName))
                    foreach (DataRow dr in dt.Rows)
                    {
                        Items.Add(dr[0]);
                    }
                else
                    foreach (DataRow dr in dt.Rows)
                    {
                        Items.Add(dr[ColumnName]);
                    }
            }
        }
        #endregion
 
        #region 重置属性或者重写属性
 
        [Category("Wen"), Description("设置单项高度"), DefaultValue(23)]
        public new int ItemHeight { get => itemHeight; set { base.ItemHeight = value; itemHeight = value; } }
 
        #endregion
 
        #region 执行重绘
 
        //重绘指定项
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            //base.OnDrawItem(e);
            if (Items.Count == 0 || e.Index < 0)
                return;
            Graphics g = e.Graphics;
            Rectangle rec = GetItemRectangle(e.Index);
            if (GetSelected(e.Index))
            {
                rec.Inflate(0, -2);
                ItemDraw(e.Index, g, rec, SelectedRowColor, e);
            }
            else if (e.Index == MouseItemIndex)
            {
                ItemDraw(e.Index, g, rec, MouseMoveRowColor, e);
            }
            else if (e.Index % 2 != 1)
            {
                ItemDraw(e.Index, g, rec, OneRowColor, e);
            }
            else
            {
                ItemDraw(e.Index, g, rec, TowRowColor, e);
            }
        }
 
        //刷新指定项目
        private void ItemDraw(int index, Graphics g, Rectangle rec, Color c, DrawItemEventArgs e)
        {
            ControlHelper.SetGDIHigh(g);
 
            using Brush backColor = new SolidBrush(c);
            g.FillRectangle(backColor, rec);
 
            using Brush brush = new SolidBrush(e.ForeColor);
 
            int radioWidth = 0;
            if (RadioBox)
            {
                radioWidth = 20;
                g.DrawEllipse(new Pen(brush) { Width = 2 }, new Rectangle(rec.X, (ItemHeight - 15) / 2 + rec.Y, 15, 15));
                if (GetSelected(index))
                    g.FillEllipse(brush, new Rectangle(rec.X + 5, (ItemHeight - 5) / 2 + rec.Y, 5, 5));
            }
 
            //绘制文字
            if (Line)
            {
                Rectangle recLine = new Rectangle(rec.X + radioWidth, rec.Y, 50 - radioWidth, this.ItemHeight);
                Rectangle recText = new Rectangle(rec.X + 50, rec.Y, rec.Width - 50, this.ItemHeight);
                g.DrawString((index + 1).ToString(), Font, brush, recLine, ControlHelper.StringConters);
                g.DrawString(Items[index]?.ToString(), Font, brush, recText, ControlHelper.StringConters);
            }
            else
            {
                Rectangle recText = new Rectangle(rec.X + radioWidth, rec.Y, rec.Width - radioWidth, this.ItemHeight);
                g.DrawString(Items[index]?.ToString(), Font, brush, recText, ControlHelper.StringConters);
            }
 
        }
 
        //鼠标移动
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
 
            int index = IndexFromPoint(e.Location);
            if (index < 0)
                return;
            if (MouseItemIndex != index)
            {
                int indexBefore = MouseItemIndex;
                MouseItemIndex = index;
 
                this.RefreshItem(index);
                this.RefreshItem(indexBefore);
            }
        }
 
        //刷新指定索引项
        protected override void RefreshItem(int index)
        {
            if (index < 0 || Items.Count == 0)
                return;
            Graphics g = CreateGraphics();
            Rectangle rec = GetItemRectangle(index);
            g.SetClip(new Rectangle(rec.X, rec.Y + 1, rec.Width, rec.Height - 1));
            if (SelectedIndex == index)
                OnDrawItem(new DrawItemEventArgs(g, Font, rec, index, DrawItemState.Selected, Color.White, this.SelectedRowColor));
            else
                OnDrawItem(new DrawItemEventArgs(g, Font, rec, index, DrawItemState.None, this.ForeColor, this.SelectedRowColor));
        }
 
        //鼠标移开事件
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            int index = MouseItemIndex;
            MouseItemIndex = -1;
            RefreshItem(index);
        }
        //选中索引变化
        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
            if (selectBefore != -1)
            {
                RefreshItem(selectBefore);
            }
            selectBefore = SelectedIndex;
            object item = this.SelectedItem;
            ItemClick?.Invoke(this, new WenListBoxEventArgs(item));
        }
        #endregion
    }
 
    public delegate void WenListBoxEventHandler(object sender, WenListBoxEventArgs e);
    public class WenListBoxEventArgs : EventArgs
    {
        public WenListBoxEventArgs(object item)
        {
            this.Item = item;
        }
        public object Item { get; set; }
    }
}