// *********************************************************************** // Assembly : Construction // Author : zjx // Created : 09-09-2020 // // Last Modified By : zjx // Last Modified On : 09-09-2020 // *********************************************************************** // // Copyright (c) jindongfang. All rights reserved. // // // *********************************************************************** using DevExpress.Utils; using DevExpress.XtraGrid.Columns; using DevExpress.XtraGrid.Views.Grid; using DevExpress.XtraGrid.Views.Grid.ViewInfo; using Fk.Utils; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Dynamic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using WorkData; using WorkData.Entity; namespace WellWorkDataUI.CustomControls { /// /// Class FrmGeologicalStratification. /// Implements the /// /// public partial class FrmGeologicalStratification : Form, IComparer { /// /// Data Changed /// internal bool DataChanged { get; private set; } = false; private List data = new List(); /// /// Initializes a new instance of the class. /// public FrmGeologicalStratification() { this.InitializeComponent(); this.LoadDataAsync(); } /// /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. /// /// x /// y /// compare result public int Compare(GeologicalStratification x, GeologicalStratification y) { GeologicalStratification a = x; GeologicalStratification b = y; do { if (a.ParentID == b.ParentID) { return a.Order.CompareTo(b.Order); } if (a.Level == b.Level) { a = this.data.FirstOrDefault(o => o.ID == a.ParentID); b = this.data.FirstOrDefault(o => o.ID == b.ParentID); } else if (a.Level > b.Level) { a = this.data.FirstOrDefault(o => o.ID == a.ParentID); } else if (a.Level < b.Level) { b = this.data.FirstOrDefault(o => o.ID == b.ParentID); } } while (a != null && b != null); return 0; } /// /// Raises the event. /// /// A that contains the event data. protected override void OnFormClosing(FormClosingEventArgs e) { if (this.DataChanged && MessageBox.Show("数据已修改, 是否保存?", "提示", MessageBoxButtons.OKCancel) == DialogResult.OK) { this.SaveData(); } base.OnFormClosing(e); } /// /// Saves the data async. /// /// A Task. private void SaveData() { DBHelp.NewDb.Ado.ExecuteCommand("PRAGMA foreign_keys = OFF;"); DBHelp.NewDb.BulkInsert(this.data, db => { db.Deleteable().ExecuteCommand(); }); this.DataChanged = false; MessageBox.Show("数据保存成功!"); DataHelp.LoadGeoLayer(); //更新当前工区变量 } private async void LoadDataAsync() { this.data.AddRange(await DBHelp.NewDb.Queryable().ToListAsync()); this.ViewData(); } private void ViewData() { ModelList list = new ModelList(); List leafs = this.data.Where(r => !this.data.Any(o => o.ParentID == r.ID)) .OrderBy(o => o, this) .ToList(); foreach (GeologicalStratification item in leafs) { dynamic model = new Model(); GeologicalStratification cur = item; do { model[$"Level{cur.Level}"] = cur.Code; model[$"Object{cur.Level}"] = cur; list.MaxLevel = Math.Max(list.MaxLevel, cur.Level); model.MaxLevel = Math.Max(model.MaxLevel, cur.Level); cur = this.data.FirstOrDefault(o => o.ID == cur.ParentID); } while (cur != null); list.Add(model); } this.gridViewMain.Columns.Clear(); for (int i = 0; i <= list.MaxLevel; i++) { GridColumn col = this.gridViewMain.Columns.Add(); col.Caption = $"{NumberConverter.NumToChinese(i + 1)}级分层"; col.FieldName = $"Level{i}"; col.Visible = true; col.OptionsColumn.AllowEdit = true; } this.gridControl1.DataSource = list; } private void btnExport_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { SaveFileDialog dlg = new SaveFileDialog() { Filter = "分隔符文件(*.txt;*.dat;*.csv)|*.txt;*.dat;*.csv|所有文件(*.*)|*.*", }; if (dlg.ShowDialog() == DialogResult.OK) { string seperator = ","; string ext = Path.GetExtension(dlg.FileName); if (ext.Equals(".txt", StringComparison.OrdinalIgnoreCase)) { seperator = "\t"; } else if (ext.Equals(".dat", StringComparison.OrdinalIgnoreCase)) { seperator = " "; } if (this.gridControl1.DataSource is ModelList list) { StringBuilder sb = new StringBuilder(); foreach (Model item in list) { if (item.MaxLevel > 0) { dynamic model = item; for (int i = 0; i <= item.MaxLevel; i++) { sb.Append(model[$"Level{i}"]); sb.Append(seperator); } sb.Length -= seperator.Length; sb.AppendLine(); } } File.WriteAllText(dlg.FileName, sb.ToString()); MessageBox.Show("导出数据成功!"); } } } private int GetNextId() { return this.data.Count > 0 ? this.data.Max(o => o.ID) + 1 : 0; } private async Task ImportDataCore(Stream stream, Encoding encoding) { await DBHelp.NewDb.UseTranAsync(async db => { Dictionary dict = new Dictionary(); using (StreamReader reader = new StreamReader(stream, encoding, true)) { int nLine = 0; while (!reader.EndOfStream) { string line = await reader.ReadLineAsync(); string[] arr = line.Split(Constants.StringSplit.Separator, StringSplitOptions.RemoveEmptyEntries); if (arr.Any(o => string.IsNullOrWhiteSpace(o))) { this.data.Clear(); MessageBox.Show("不能为空"); return; } GeologicalStratification parent = null; for (int i = 0; i < arr.Length; i++) { GeologicalStratification cur = null; string key = $"{arr[i]}-{i}"; if (dict.ContainsKey(key)) { cur = dict[key]; } else { cur = new GeologicalStratification() { ID = this.GetNextId(), Code = arr[i], Level = i, Order = nLine, ParentID = parent?.ID ?? -1, }; dict[key] = cur; this.data.Add(cur); } parent = cur; } nLine++; } } }); } private async void btnPaste_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (Clipboard.ContainsText()) { Encoding encoding = Encoding.Default; using (MemoryStream stream = new MemoryStream(encoding.GetBytes(Clipboard.GetText()))) { await this.ImportDataCore(stream, encoding); } this.ViewData(); this.DataChanged = true; MessageBox.Show("粘贴数据成功!"); } } private async void btnImport_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { OpenFileDialog dlg = new OpenFileDialog() { Filter = "分隔符文件(*.txt;*.dat;*.csv)|*.txt;*.dat;*.csv|所有文件(*.*)|*.*", }; if (dlg.ShowDialog() == DialogResult.OK) { Encoding charset2 = EncodingType.GetType(dlg.FileName); //using (var mmf = MemoryMappedFile.CreateFromFile(dlg.FileName, FileMode.Open, Guid.NewGuid().ToString())) //using (var stream = mmf.CreateViewStream(0, 0)) using (MemoryStream stream = new MemoryStream(File.ReadAllBytes(dlg.FileName))) { await this.ImportDataCore(stream, charset2); } this.ViewData(); this.DataChanged = true; MessageBox.Show("导入数据成功!"); } } private void btnExit_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.DialogResult = DialogResult.Cancel; } private void btnSave_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.SaveData(); this.DialogResult = DialogResult.OK; } private void btnDeleteAll_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.DataChanged = true; this.data.Clear(); this.ViewData(); } /// /// 删除项 /// private void btnDelete_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { int[] rows = this.gridViewMain.GetSelectedRows(); if (rows.Length > 0) { this.DataChanged = true; foreach (int handle in rows) { dynamic model = this.gridViewMain.GetRow(handle); if (model[$"Object{model.MaxLevel}"] is GeologicalStratification gs) { this.data.Remove(gs); } } this.ViewData(); } } private void btnAdd_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (this.gridControl1.DataSource is ModelList list) { this.DataChanged = true; dynamic model = this.gridViewMain.GetRow(this.gridViewMain.RowCount - 1); dynamic newmodel = new Model(); if (model != null) { newmodel.MaxLevel = model.MaxLevel; for (int i = 0; i <= model.MaxLevel - 1; i++) { newmodel[$"Level{i}"] = model[$"Level{i}"]; newmodel[$"Object{i}"] = model[$"Object{i}"]; } if (model[$"Object{model.MaxLevel}"] is GeologicalStratification gs) { GeologicalStratification newgs = new GeologicalStratification { ID = this.GetNextId(), Level = gs.Level, Order = gs.Order + 1, ParentID = gs.ParentID, Code = "新建分层", }; this.data.Add(newgs); newmodel[$"Level{model.MaxLevel}"] = newgs.Code; newmodel[$"Object{model.MaxLevel}"] = newgs; } } else { GeologicalStratification newgs = new GeologicalStratification { ID = this.GetNextId(), Level = 0, Order = 0, ParentID = -1, Code = "新建分层", }; this.data.Add(newgs); newmodel[$"Level0"] = newgs.Code; newmodel[$"Object0"] = newgs; } list.Add(newmodel); } } private void btnInsert_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { int handle = this.gridViewMain.FocusedRowHandle; if (this.gridControl1.DataSource is ModelList list && handle >= 0) { this.DataChanged = true; dynamic model = this.gridViewMain.GetRow(handle); dynamic newmodel = new Model() { MaxLevel = model.MaxLevel }; for (int i = 0; i <= model.MaxLevel - 1; i++) { newmodel[$"Level{i}"] = model[$"Level{i}"]; newmodel[$"Object{i}"] = model[$"Object{i}"]; } if (model[$"Object{model.MaxLevel}"] is GeologicalStratification gs) { GeologicalStratification newgs = new GeologicalStratification { ID = this.GetNextId(), Level = gs.Level, Order = gs.Order + 1, ParentID = gs.ParentID, Code = "新建分层", }; this.data.Add(newgs); newmodel[$"Level{model.MaxLevel}"] = newgs.Code; newmodel[$"Object{model.MaxLevel}"] = newgs; List nextList = this.data.Where(o => o.ParentID == gs.ParentID && o.Order > gs.Order) .ToList(); foreach (GeologicalStratification item in nextList) { item.Order += 1; } } list.Insert(this.gridViewMain.FocusedRowHandle + 1, newmodel); } } private void gridViewMain_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e) { //if (string.IsNullOrWhiteSpace(e.Value?.ToString())) //{ // var oldValue = this.gridViewMain.ActiveEditor.OldEditValue; // this.gridViewMain.SetRowCellValue(e.RowHandle, e.Column, oldValue); // MessageBox.Show("数据不能为空!"); // return; //} if (e.RowHandle >= 0) { dynamic model = this.gridViewMain.GetRow(e.RowHandle); int idx = e.Column.AbsoluteIndex; if (model[$"Object{idx}"] is GeologicalStratification gs) { this.DataChanged = true; gs.Code = e.Value.ToString(); } else { if (model[$"Object{model.MaxLevel}"] is GeologicalStratification parent) { var parentId = this.data.Count == 0 ? -1 : parent.ID; GeologicalStratification newgs = new GeologicalStratification { ID = this.GetNextId(), Code = e.Value.ToString(), Level = idx, Order = 0, ParentID = parentId, }; model[$"Object{idx}"] = newgs; model.MaxLevel = newgs.Level; this.data.Add(newgs); this.DataChanged = true; } } } } private void gridViewMain_MouseDown(object sender, MouseEventArgs e) { GridView view = sender as GridView; GridHitInfo hitInfo = view.CalcHitInfo(e.Location); if (hitInfo.InRowCell) { hitInfo.Column.OptionsColumn.AllowEdit = true; view.ClearSelection(); view.SelectRow(hitInfo.RowHandle); view.FocusedRowHandle = hitInfo.RowHandle; view.FocusedColumn = hitInfo.Column; DXMouseEventArgs.GetMouseArgs(e).Handled = true; if (e.Clicks == 2 && e.Button == MouseButtons.Left) { view.ShowEditor(); view.ActiveEditor.SelectAll(); } } } private void gridViewMain_FocusedColumnChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedColumnChangedEventArgs e) { } private class Model : DynamicObject { private readonly Dictionary dynamicProperties = new Dictionary(); public int MaxLevel { get; set; } = 0; public override bool TrySetMember(SetMemberBinder binder, object value) { this.dynamicProperties[binder.Name] = value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (!this.dynamicProperties.TryGetValue(binder.Name, out result)) { result = string.Empty; } return true; } public override IEnumerable GetDynamicMemberNames() { return this.dynamicProperties.Keys; } public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) { string key = (string)indexes[0]; this.dynamicProperties[key] = value; return true; } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { string key = (string)indexes[0]; if (!this.dynamicProperties.TryGetValue(key, out result)) { result = string.Empty; } return true; } } private class ModelList : AsyncBindingList, ITypedList { public int MaxLevel { get; set; } = 4; public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) { List descriptors = new List(); for (int i = 0; i <= this.MaxLevel; i++) { descriptors.Add(new MyDynamicPropertyDescriptor($"Level{i}", typeof(string))); } return new PropertyDescriptorCollection(descriptors.ToArray()); } public string GetListName(PropertyDescriptor[] listAccessors) { throw new NotImplementedException(); } private class MyDynamicPropertyDescriptor : PropertyDescriptor { public MyDynamicPropertyDescriptor(string name, Type type) : base(name, null) { this.Type = type; } public Type Type { get; private set; } public override bool IsReadOnly => false; public override Type PropertyType => this.Type; public override Type ComponentType => typeof(Model); public override bool CanResetValue(object component) => throw new NotImplementedException(); public override void ResetValue(object component) => throw new NotImplementedException(); public override bool ShouldSerializeValue(object component) => throw new NotImplementedException(); public override object GetValue(object component) { dynamic model = component as Model; return model[this.Name]; } public override void SetValue(object component, object value) { dynamic model = component as Model; model[this.Name] = value; } } } } }