1
yhj
2024-07-24 5e5d945e91568b973faa27d8ab0bcef99fc4a6c5
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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#region
 
using System;
using System.Collections;
using System.Data;
using System.Windows.Forms;
using CSFrameworkV5.Core;
using DevExpress.XtraGrid.Views.Grid;
 
#endregion
 
namespace CSFrameworkV5.Library
{
    public partial class frmRowPositionAdjustor : Form
    {
        private static Hashtable _HS = new Hashtable();
        private IRowAdjustor _Adjustor;
 
        public frmRowPositionAdjustor()
        {
            InitializeComponent();
        }
 
        private static void AddMenu(GridView gv, string sortFieldName)
        {
            //添加分隔条菜单项
            gv.GridControl.ContextMenuStrip.Items.Add("-");
 
            //添加菜单项
            var img = new frmRowPositionAdjustor().imageList1.Images[0];
            var menuItem =
                gv.GridControl.ContextMenuStrip.Items.Add("调整行位置", img,
                    On_Adjustor_Click);
            menuItem.Name = "menuRowAdjustor";
            menuItem.Tag = new RowAdjustorMenuItemTag
                { GridView = gv, SortFieldName = sortFieldName };
        }
 
        private void btnFirst_Click(object sender, EventArgs e)
        {
            _Adjustor.ToFirst();
        }
 
        private void btnLast_Click(object sender, EventArgs e)
        {
            _Adjustor.ToLast();
        }
 
        private void btnNext_Click(object sender, EventArgs e)
        {
            _Adjustor.ToNext();
        }
 
        private void btnPrior_Click(object sender, EventArgs e)
        {
            _Adjustor.ToPrior();
        }
 
        private void btnReset_Click(object sender, EventArgs e)
        {
            _Adjustor.Reset();
        }
 
        /// <summary>
        ///     打开排序调整界面
        /// </summary>
        /// <param name="owner">父级窗体</param>
        /// <param name="grid">表格组件</param>
        /// <param name="sortFieldName">排序字段名称</param>
        /// <param name="autoClose">自动关闭排序调整窗体,C/S开发框架调用必须设为True,其他调用设为False</param>
        public static void Execute(Form owner, GridView grid,
            string sortFieldName, bool autoClose = false)
        {
            if (owner == null) throw new Exception("必须指定父级窗体!");
 
            var form = new frmRowPositionAdjustor();
            form._Adjustor = new GridViewRowAdjustor(grid, sortFieldName);
            form.TopMost = true;
            form.Owner = owner;
            form.SetPosition(grid);
            form.Show();
 
            //自动关闭排序调整窗体
            if (autoClose)
            {
                owner.FormClosing += Owner_FormClosing;
                owner.Deactivate += Owner_Deactivate;
                _HS.Add(owner, form);
            }
        }
 
        //关闭当前窗体(Adjustor Form)
        private void frmRowPositionAdjustor_FormClosed(object sender,
            FormClosedEventArgs e)
        {
            if (_HS.Contains(Owner)) _HS.Remove(Owner);
        }
 
        private static void On_Adjustor_Click(object sender, EventArgs e)
        {
            var tag = (sender as ToolStripItem).Tag as RowAdjustorMenuItemTag;
            Execute(tag.GridView.GridControl.FindForm(), tag.GridView,
                tag.SortFieldName, true);
        }
 
        //父级窗体失去焦点事件
        private static void Owner_Deactivate(object sender, EventArgs e)
        {
            if (_HS.Contains(sender as Form))
            {
                (_HS[sender as Form] as frmRowPositionAdjustor).Close();
                _HS.Remove(sender as Form);
            }
        }
 
        //父级窗体关闭事件
        private static void Owner_FormClosing(object sender,
            FormClosingEventArgs e)
        {
            if (_HS.Contains(sender as Form))
            {
                (_HS[sender as Form] as frmRowPositionAdjustor).Close();
                _HS.Remove(sender as Form);
            }
        }
 
        /// <summary>
        ///     注册表格组件,自动创建弹出菜单
        /// </summary>
        /// <param name="gv">表格组件</param>
        /// <param name="sortFieldName">排序字段名称</param>
        public static void Register(GridView gv, string sortFieldName)
        {
            var menu = gv.GridControl.ContextMenuStrip;
 
            if (menu == null)
            {
                gv.GridControl.ContextMenuStrip = new ContextMenuStrip();
                AddMenu(gv, sortFieldName);
            }
            else
            {
                var items = menu.Items.Find("menuRowAdjustor", true);
                if (items.Length == 0) AddMenu(gv, sortFieldName);
            }
        }
 
        //设置窗体的显示位置
        private void SetPosition(GridView grid)
        {
            var form = grid.GridControl.FindForm();
            StartPosition = FormStartPosition.Manual;
 
            //int X = grid.GridControl.Left + form.Left+150;
            //int Y = grid.GridControl.Top + form.Top;
            //this.Location = new Point(X, Y);            
 
            var P = grid.GridControl.PointToScreen(grid.GridControl.Location);
            P.X += 100;
            P.Y += 20;
            Location = P;
        }
    }
 
    public class RowAdjustorMenuItemTag
    {
        public GridView GridView { get; set; }
 
        public string SortFieldName { get; set; }
    }
 
    /// <summary>
    ///     位置调整接口
    /// </summary>
    public interface IRowAdjustor
    {
        /// <summary>
        ///     重置排序序号
        /// </summary>
        decimal Reset();
 
        void ToFirst();
 
        void ToLast();
 
        void ToNext();
 
        void ToPrior();
    }
 
    /// <summary>
    ///     DevExpress GridView表格记录行位置调整器 - C/S框架网 - www.cscode.net
    /// </summary>
    public class GridViewRowAdjustor : IRowAdjustor
    {
        private int _FirstSortID = 1; //默认初始序号(第一条记录的序号)
        private GridView _GridView;
        private string _SortFieldName; //用于排序的字段名称
 
        public GridViewRowAdjustor(GridView view, string sortFieldName)
        {
            _GridView = view;
            _SortFieldName = sortFieldName;
 
            //设置排序字段
            DataSource.DefaultView.Sort = sortFieldName + " ASC";
 
            CheckSortValue(true);
        }
 
        private DataTable DataSource =>
            _GridView.GridControl.DataSource as DataTable;
 
        public decimal Reset()
        {
            if (_GridView.RowCount == 0) return 0;
 
            var i = _FirstSortID; //初始序号
 
            //枚举DataView的记录,重新设置序号
            //不能直接枚举DataView.Table对象的记录,这是原始记录
            DataRow row;
            var enu = DataSource.DefaultView.GetEnumerator();
            while (enu.MoveNext())
            {
                row = (enu.Current as DataRowView).Row;
                //跳过被删除的记录
                if (row.RowState != DataRowState.Deleted)
                {
                    row[_SortFieldName] = i;
                    i++;
                }
            }
 
            _GridView.GridControl.RefreshDataSource();
            _GridView.FocusedRowHandle = 0;
 
            return i;
        }
 
        public void ToFirst()
        {
            //当前记录是第一条记录,不处理
            if (_GridView.FocusedRowHandle == 0) return;
 
            //当前记录
            var R = _GridView.GetFocusedDataRow();
 
            //原始第1条记录的序号
            var R_Old = _GridView.GetDataRow(0);
            var sort = GetSortValue(R_Old[_SortFieldName]);
            R[_SortFieldName] = sort / 2; //当前记录的序号=原始第1条记录的序号/2,所以排在前面
            _GridView.GridControl.RefreshDataSource();
        }
 
        public void ToLast()
        {
            //当前记录是最后一条记录,不处理
            if (_GridView.FocusedRowHandle == _GridView.RowCount - 1) return;
 
            //当前记录
            var R = _GridView.GetFocusedDataRow();
 
            //原始最后一条记录的序号
            var R_Old = _GridView.GetDataRow(_GridView.RowCount - 1);
            var sort = GetSortValue(R_Old[_SortFieldName]);
            R[_SortFieldName] = sort + 1; //最后序号+1,排序最后
 
            _GridView.GridControl.RefreshDataSource();
        }
 
        public void ToNext()
        {
            //当前记录是最后一条记录,不处理
            if (_GridView.FocusedRowHandle == _GridView.RowCount - 1) return;
 
            //当前记录
            var R1 = _GridView.GetFocusedDataRow();
            var sort1 = GetSortValue(R1[_SortFieldName]);
 
            //取下1条记录
            var R2 = _GridView.GetDataRow(_GridView.FocusedRowHandle + 1);
            var sort2 = GetSortValue(R2[_SortFieldName]);
 
            //交换序号
            R1[_SortFieldName] = sort2;
            R2[_SortFieldName] = sort1;
 
            _GridView.GridControl.RefreshDataSource();
        }
 
        public void ToPrior()
        {
            //当前记录是第一条记录,不处理
            if (_GridView.FocusedRowHandle == 0) return;
 
            //当前记录
            var R1 = _GridView.GetFocusedDataRow();
            var sort1 = GetSortValue(R1[_SortFieldName]);
 
            //取上一条记录
            var R2 = _GridView.GetDataRow(_GridView.FocusedRowHandle - 1);
            var sort2 = GetSortValue(R2[_SortFieldName]);
 
            //交换序号
            R1[_SortFieldName] = sort2;
            R2[_SortFieldName] = sort1;
 
            _GridView.GridControl.RefreshDataSource();
        }
 
        /// <summary>
        ///     检测排序字段的值
        /// </summary>
        /// <param name="resetIfNullValue">True:若检测排序字段的值为空,自动重置排序ID, False:不排序</param>
        /// <returns></returns>
        private bool CheckSortValue(bool resetIfNullValue)
        {
            var hasNullValue = false;
            foreach (DataRow R in DataSource.Rows)
                if (R[_SortFieldName] == DBNull.Value //空值
                    || R[_SortFieldName].ToStringEx().Trim() == "" //空值
                    || Convert.ToDecimal(R[_SortFieldName].ToStringEx()
                        .Trim()) == 0) //等于0
                {
                    hasNullValue = true;
                    break;
                }
 
            if (hasNullValue && resetIfNullValue) Reset();
 
            return hasNullValue;
        }
 
        private decimal GetSortValue(object fieldValue)
        {
            if (fieldValue == DBNull.Value) return 0;
 
            return Convert.ToDecimal(fieldValue);
        }
    }
}