Compare commits
3 Commits
f665688d0b
...
7d8ad77f5c
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d8ad77f5c | |||
| f72b153eb6 | |||
| c49015d390 |
+7
-3
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
@@ -666,4 +670,4 @@
|
||||
private Control.TabControlEx tab_basicInfo;
|
||||
private DevExpress.XtraEditors.DropDownButton btnPrint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace Lskj.BaseAccraditation
|
||||
/// 主表控件
|
||||
/// </summary>
|
||||
public MyControl ControlObj;
|
||||
private bool mResourcesReleased;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -191,6 +192,42 @@ namespace Lskj.BaseAccraditation
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
PrintUtil.OnAfterPrint -= OnReportPrintAfter;
|
||||
|
||||
MyControl control = ControlObj;
|
||||
ControlObj = null;
|
||||
if (control != null)
|
||||
{
|
||||
control.OnDataSourceBindCallBack -=
|
||||
OnControlObjOnDataSourceBindCallBack;
|
||||
control.Dispose();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (tab_basicInfo != null)
|
||||
{
|
||||
tab_basicInfo.ParentControlEx = null;
|
||||
}
|
||||
if (SysModel != null && SysModel.DataCaches != null)
|
||||
{
|
||||
SysModel.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A partially disposed child must not stop form cleanup.
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetFormSize()
|
||||
{
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
|
||||
Generated
+7
-2
@@ -13,9 +13,14 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
Lskj.Control.Model.PrintUtil.OnAfterPrint -=
|
||||
new System.EventHandler(OnReportPrintAfter);
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -41,11 +41,79 @@ namespace Lskj.Control
|
||||
{
|
||||
public partial class AuditPanelEx : UserControl
|
||||
{
|
||||
private bool mResourcesReleased;
|
||||
|
||||
public AuditPanelEx()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
internal void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
MyControl searchControl = _searchContrl;
|
||||
_searchContrl = null;
|
||||
if (searchControl != null)
|
||||
{
|
||||
searchControl.Dispose();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (gridFinish != null && gridFinish.GridView != null)
|
||||
{
|
||||
gridFinish.GridView.SelectionChanged -= GvFinish_SelectionChangedClick;
|
||||
gridFinish.GridView.DoubleClick -= GvFinish_DoubleClick;
|
||||
}
|
||||
foreach (TabPageObj tabPage in _tabPageObjs)
|
||||
{
|
||||
foreach (TabPageItemObj item in tabPage.TabPageItemObjs)
|
||||
{
|
||||
if (item.GridControlObj != null &&
|
||||
item.GridControlObj.GridView != null)
|
||||
{
|
||||
item.GridControlObj.GridView.DoubleClick -=
|
||||
OnGridViewDoubleClick;
|
||||
item.GridControlObj.Model = null;
|
||||
}
|
||||
}
|
||||
tabPage.TabPageItemObjs.Clear();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A partially disposed DevExpress view must not stop cleanup.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (SysModel != null && SysModel.DataCaches != null)
|
||||
{
|
||||
SysModel.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt control disposal.
|
||||
}
|
||||
|
||||
_tabPageObjs.Clear();
|
||||
_tabPageCount.Clear();
|
||||
OnGridViewDoubleCallBack = null;
|
||||
OnGridFinshViewDoubleCallBack = null;
|
||||
OnBtnSearchCallBack = null;
|
||||
SectionAccradit = null;
|
||||
AuditComModelObj = null;
|
||||
BaseAccraditModelObj = null;
|
||||
PubSysModel = null;
|
||||
SysModel = null;
|
||||
}
|
||||
|
||||
#region 公有变量
|
||||
|
||||
/// <summary>
|
||||
@@ -299,17 +367,12 @@ namespace Lskj.Control
|
||||
{
|
||||
return new AccraditationModel(dataRow);
|
||||
}));
|
||||
Task<GridControlEx> gridControlExTask = cachesDic.AddTask(dataRow, "GridControlEx", new Task<GridControlEx>(() =>
|
||||
{
|
||||
return new GridControlEx();
|
||||
}));
|
||||
GridControlEx gridControlEx = gridControlExTask.Result;
|
||||
string key = "FLOWSTEP_" + dynamicModel.ModuleCode + "_" + flowTypeStepModelTask.Result.StepCode + "_" + accraditationModelTask.Result.Id + "";
|
||||
Task<DataTable> baseGridRowColorsTask = cachesDic.AddTask(gridControlEx, "BaseGridRowColors", new Task<DataTable>(() =>
|
||||
Task<DataTable> baseGridRowColorsTask = cachesDic.AddTask(dataRow, "BaseGridRowColors", new Task<DataTable>(() =>
|
||||
{
|
||||
return BaseModuleImpl.GetBaseGridRowColors(key);
|
||||
}));
|
||||
Task<DataTable> flowstepGridRightMenusTask = cachesDic.AddTask(gridControlEx, "FlowstepGridRightMenus", new Task<DataTable>(() =>
|
||||
Task<DataTable> flowstepGridRightMenusTask = cachesDic.AddTask(dataRow, "FlowstepGridRightMenus", new Task<DataTable>(() =>
|
||||
{
|
||||
return BaseModuleImpl.GetBaseGridRightMenus($"FLOWSTEP_{accraditationModelTask.Result.Formkey}");
|
||||
}));
|
||||
@@ -317,10 +380,6 @@ namespace Lskj.Control
|
||||
//{
|
||||
// return BaseImpl.GetDataTableResult(accraditationModelTask.Result.StepSql);
|
||||
//}));
|
||||
string modelkeyName = isBill ? GridCustomColumnStruct.AuditMainGridView : GridCustomColumnStruct.BaseAuditMainGridView;
|
||||
string customColumKey = modelkeyName + key;
|
||||
cachesDic.AddTask(gridControlEx, "DynamicModel", dynamicModelTask);
|
||||
gridControlEx.GetDataCaches(cachesDic, customColumKey);
|
||||
}
|
||||
return flowList;
|
||||
}));
|
||||
@@ -613,18 +672,19 @@ namespace Lskj.Control
|
||||
gridPanel.Padding = new System.Windows.Forms.Padding(2);
|
||||
gridPanel.Dock = DockStyle.Right;
|
||||
gridPanel.BorderStyle = BorderStyles.NoBorder;
|
||||
if (!dataCaches.GetValue(dataRow, "GridControlEx", out GridControlEx grid))
|
||||
GridControlEx grid = new GridControlEx();
|
||||
if (dataCaches != null)
|
||||
{
|
||||
grid = new GridControlEx();
|
||||
grid.GetDataCaches(dataCaches, modelkeyName + key);
|
||||
}
|
||||
grid.Parent = gridPanel;
|
||||
grid.Dock = DockStyle.Fill;
|
||||
grid.BorderStyle = BorderStyle.None;
|
||||
if (!dataCaches.GetValue(grid, "BaseGridRowColors", out DataTable dtGridRowColors))
|
||||
if (!dataCaches.GetValue(dataRow, "BaseGridRowColors", out DataTable dtGridRowColors))
|
||||
{
|
||||
dtGridRowColors = BaseModuleImpl.GetBaseGridRowColors(key);
|
||||
}
|
||||
if (!dataCaches.GetValue(grid, "FlowstepGridRightMenus", out DataTable dtGridRightMenus))
|
||||
if (!dataCaches.GetValue(dataRow, "FlowstepGridRightMenus", out DataTable dtGridRightMenus))
|
||||
{
|
||||
dtGridRightMenus = BaseModuleImpl.GetBaseGridRightMenus($"FLOWSTEP_{accrModel.Formkey}");
|
||||
}
|
||||
@@ -1906,4 +1966,4 @@ namespace Lskj.Control
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,17 +78,17 @@ namespace Lskj.Control.BrowserSetting
|
||||
string arg2 = message.Arguments.GetString(2);
|
||||
string arg3 = message.Arguments.GetString(3);
|
||||
string arg4 = message.Arguments.GetString(4);
|
||||
if (ERPInfo.Instance.MainControl.InvokeRequired)
|
||||
{
|
||||
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
|
||||
PostToUiThread(
|
||||
ERPInfo.Instance.MainControl,
|
||||
delegate
|
||||
{
|
||||
BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
BrowserSetting.BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
BsOpenModuleHandler.OpenModule(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4);
|
||||
});
|
||||
}
|
||||
else if (message.Name.Equals("OpenOnRightClick"))
|
||||
{
|
||||
@@ -96,75 +96,103 @@ namespace Lskj.Control.BrowserSetting
|
||||
string arg1 = message.Arguments.GetString(1);
|
||||
string arg2 = message.Arguments.GetString(2);
|
||||
string arg3 = message.Arguments.GetString(3);
|
||||
if (ERPInfo.Instance.MainControl.InvokeRequired)
|
||||
{
|
||||
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
|
||||
PostToUiThread(
|
||||
ERPInfo.Instance.MainControl,
|
||||
delegate
|
||||
{
|
||||
BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
BsOpenModuleHandler.OpenRightModule(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3);
|
||||
});
|
||||
}
|
||||
else if (message.Name.Equals("CloseWin"))
|
||||
{
|
||||
if (frmWebBrowser != null && frmWebBrowser.Parent != null && frmWebBrowser.Parent.Parent != null && frmWebBrowser.Parent.Parent is BaseForm baseForm)
|
||||
{
|
||||
if (baseForm.InvokeRequired)
|
||||
{
|
||||
baseForm.Invoke(new Action(() =>
|
||||
{
|
||||
baseForm.DialogResult = DialogResult.OK;
|
||||
baseForm.Close();
|
||||
}));
|
||||
}
|
||||
else
|
||||
var browserControl = frmWebBrowser;
|
||||
PostToUiThread(
|
||||
browserControl,
|
||||
delegate
|
||||
{
|
||||
// Parent/Parent is a WinForms control-tree read and must
|
||||
// not run on CEF's UI thread.
|
||||
var parent = browserControl.Parent;
|
||||
var baseForm = parent == null
|
||||
? null
|
||||
: parent.Parent as BaseForm;
|
||||
if (baseForm == null || baseForm.IsDisposed)
|
||||
return;
|
||||
|
||||
baseForm.DialogResult = DialogResult.OK;
|
||||
baseForm.Close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (message.Name.Equals("SelectPro"))
|
||||
{
|
||||
string arg0 = message.Arguments.GetString(0);
|
||||
string arg1 = message.Arguments.GetString(1);
|
||||
bool isclose = arg1!=null&&!string.IsNullOrWhiteSpace(arg1) && arg1.Equals("1") ? true : false;
|
||||
if (frmWebBrowser != null && frmWebBrowser.Parent != null && frmWebBrowser.Parent.Parent != null && frmWebBrowser.Parent.Parent is BaseForm baseForm)
|
||||
{
|
||||
if (baseForm.InvokeRequired)
|
||||
{
|
||||
baseForm.Invoke(new Action(() =>
|
||||
{
|
||||
BsOpenModuleHandler.AddReturnRow(arg0);
|
||||
if (isclose)
|
||||
{
|
||||
baseForm.DialogResult = DialogResult.OK;
|
||||
baseForm.Close();
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
else
|
||||
var browserControl = frmWebBrowser;
|
||||
PostToUiThread(
|
||||
browserControl,
|
||||
delegate
|
||||
{
|
||||
var parent = browserControl.Parent;
|
||||
var baseForm = parent == null
|
||||
? null
|
||||
: parent.Parent as BaseForm;
|
||||
if (baseForm == null || baseForm.IsDisposed)
|
||||
return;
|
||||
|
||||
BsOpenModuleHandler.AddReturnRow(arg0);
|
||||
if (isclose)
|
||||
if (isclose)
|
||||
{
|
||||
baseForm.DialogResult = DialogResult.OK;
|
||||
baseForm.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return base.OnProcessMessageReceived(browser, frame, sourceProcess, message);
|
||||
}
|
||||
|
||||
private static void PostToUiThread(
|
||||
System.Windows.Forms.Control control,
|
||||
Action action)
|
||||
{
|
||||
if (control == null || action == null || control.IsDisposed ||
|
||||
!control.IsHandleCreated)
|
||||
return;
|
||||
|
||||
Action guardedAction = delegate
|
||||
{
|
||||
if (control.IsDisposed)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ReportProcessMessageFailure(exception);
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// CEF invokes OnProcessMessageReceived on its UI thread. A
|
||||
// synchronous Control.Invoke can block that thread inside a
|
||||
// modal dialog while the dialog waits for CEF to create its
|
||||
// browser. Always queue the operation and return to CEF first.
|
||||
control.BeginInvoke(guardedAction);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ReportProcessMessageFailure(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReportProcessMessageFailure(Exception exception)
|
||||
{
|
||||
try
|
||||
@@ -173,10 +201,10 @@ namespace Lskj.Control.BrowserSetting
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Logging must never rethrow across the native CEF callback.
|
||||
// Never propagate logging failures into a native CEF callback.
|
||||
}
|
||||
|
||||
Action showError = () =>
|
||||
Action showError = delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -184,14 +212,14 @@ namespace Lskj.Control.BrowserSetting
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Error reporting must never terminate the browser callback.
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
System.Windows.Forms.Control mainControl = ERPInfo.Instance.MainControl;
|
||||
if (mainControl == null || mainControl.IsDisposed || !mainControl.IsHandleCreated)
|
||||
if (mainControl == null || mainControl.IsDisposed ||
|
||||
!mainControl.IsHandleCreated)
|
||||
return;
|
||||
|
||||
if (mainControl.InvokeRequired)
|
||||
@@ -201,15 +229,36 @@ namespace Lskj.Control.BrowserSetting
|
||||
}
|
||||
catch
|
||||
{
|
||||
// The main window may close while the CEF callback is reporting.
|
||||
// The main window may close while the callback is reporting.
|
||||
}
|
||||
}
|
||||
|
||||
public void Created(CefBrowser cefBrowser)
|
||||
{
|
||||
if (OnCreated != null)
|
||||
if (frmWebBrowser != null && OnCreated != null)
|
||||
{
|
||||
OnCreated(cefBrowser, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Closing(CefBrowser browser)
|
||||
{
|
||||
var control = frmWebBrowser;
|
||||
return control != null && control.BrowserClosing(browser);
|
||||
}
|
||||
|
||||
public void Closed(CefBrowser browser)
|
||||
{
|
||||
var control = frmWebBrowser;
|
||||
if (control != null)
|
||||
{
|
||||
control.BrowserClosed(browser);
|
||||
if (control.cefBrowserSettings == null)
|
||||
{
|
||||
frmWebBrowser = null;
|
||||
OnCreated = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Lskj.Control.BrowserSetting
|
||||
}
|
||||
if (BsClient != null && BsClient.frmWebBrowser != null && BsClient.frmWebBrowser.Parent != null && BsClient.frmWebBrowser.Parent.Name.Equals("previewFrm"))
|
||||
{
|
||||
browser.GetHost().CloseBrowser();
|
||||
BsClient.frmWebBrowser.CloseBrowser();
|
||||
}
|
||||
else if (BsClient != null && BsClient.frmWebBrowser != null)
|
||||
{
|
||||
@@ -196,11 +196,24 @@ namespace Lskj.Control.BrowserSetting
|
||||
try
|
||||
{
|
||||
if (browser == null) return null;
|
||||
IntPtr browserHandle = browser.GetHost().GetWindowHandle();
|
||||
IntPtr browserHandle;
|
||||
using (var browserHost = browser.GetHost())
|
||||
{
|
||||
browserHandle = browserHost.GetWindowHandle();
|
||||
}
|
||||
if (browserHandle == IntPtr.Zero) return null;
|
||||
IntPtr parentHandle = GetParent(browserHandle);
|
||||
if (parentHandle == IntPtr.Zero) return null;
|
||||
System.Windows.Forms.Control control = System.Windows.Forms.Control.FromHandle(parentHandle);
|
||||
System.Windows.Forms.Control control = null;
|
||||
while (parentHandle != IntPtr.Zero && control == null)
|
||||
{
|
||||
// The CEF child now sits inside an application-owned native
|
||||
// host. Walk through that host to preserve the original
|
||||
// FrmWebBrowser-based module lookup.
|
||||
control = System.Windows.Forms.Control.FromHandle(parentHandle);
|
||||
parentHandle = GetParent(parentHandle);
|
||||
}
|
||||
|
||||
if (control == null) return null;
|
||||
|
||||
if (control != null && control.Parent != null && control.Parent.Parent != null)
|
||||
{
|
||||
|
||||
@@ -20,9 +20,20 @@ namespace Lskj.Control.BrowserSetting
|
||||
base.OnAfterCreated(browser);
|
||||
BsClient.Created(browser);
|
||||
}
|
||||
|
||||
protected override bool DoClose(CefBrowser browser)
|
||||
{
|
||||
// CEF sends WM_CLOSE to the parked application-owned host after
|
||||
// this callback. The host only allows that second close attempt.
|
||||
return BsClient.Closing(browser);
|
||||
}
|
||||
|
||||
protected override void OnBeforeClose(CefBrowser browser)
|
||||
{
|
||||
base.OnBeforeClose(browser);
|
||||
|
||||
// Release owner references after CEF completes its async close.
|
||||
BsClient.Closed(browser);
|
||||
}
|
||||
|
||||
protected override bool OnBeforePopup(
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xilium.CefGlue;
|
||||
using Lskj.Business;
|
||||
|
||||
namespace Lskj.Control.BrowserSetting
|
||||
{
|
||||
@@ -46,7 +47,12 @@ namespace Lskj.Control.BrowserSetting
|
||||
|
||||
protected override void OnRenderProcessTerminated(CefBrowser browser, CefTerminationStatus status)
|
||||
{
|
||||
browser.Reload();
|
||||
// Reloading immediately from this callback can create a new
|
||||
// renderer while the old one is tearing down and cause a native
|
||||
// libcef crash loop. Record the termination and let the module
|
||||
// lifecycle decide whether a later reopen is appropriate.
|
||||
LogUtil.WriteError("CEF 渲染进程已终止,状态=" + status,
|
||||
new InvalidOperationException("CEF renderer termination status=" + status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Lskj.Business;
|
||||
using Lskj.Model;
|
||||
using Lskj.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -54,6 +55,19 @@ namespace Lskj.Control.BrowserSetting2
|
||||
return contextMenuHandler;
|
||||
}
|
||||
protected override bool OnProcessMessageReceived(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
|
||||
{
|
||||
try
|
||||
{
|
||||
return OnProcessMessageReceivedCore(browser, frame, sourceProcess, message);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ReportProcessMessageFailure(exception);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnProcessMessageReceivedCore(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
|
||||
{
|
||||
if (message.Name.Equals("OpenModule"))
|
||||
{
|
||||
@@ -62,17 +76,17 @@ namespace Lskj.Control.BrowserSetting2
|
||||
string arg2 = message.Arguments.GetString(2);
|
||||
string arg3 = message.Arguments.GetString(3);
|
||||
string arg4 = message.Arguments.GetString(4);
|
||||
if (ERPInfo.Instance.MainControl.InvokeRequired)
|
||||
{
|
||||
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
|
||||
PostToUiThread(
|
||||
ERPInfo.Instance.MainControl,
|
||||
delegate
|
||||
{
|
||||
BrowserSetting.BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
BrowserSetting.BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
BrowserSetting.BsOpenModuleHandler.OpenModule(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4);
|
||||
});
|
||||
}
|
||||
else if (message.Name.Equals("OpenOnRightClick"))
|
||||
{
|
||||
@@ -80,43 +94,140 @@ namespace Lskj.Control.BrowserSetting2
|
||||
string arg1 = message.Arguments.GetString(1);
|
||||
string arg2 = message.Arguments.GetString(2);
|
||||
string arg3 = message.Arguments.GetString(3);
|
||||
if (ERPInfo.Instance.MainControl.InvokeRequired)
|
||||
{
|
||||
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
|
||||
PostToUiThread(
|
||||
ERPInfo.Instance.MainControl,
|
||||
delegate
|
||||
{
|
||||
BrowserSetting.BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
BrowserSetting.BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
BrowserSetting.BsOpenModuleHandler.OpenRightModule(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3);
|
||||
});
|
||||
}
|
||||
else if (message.Name.Equals("CloseWin"))
|
||||
{
|
||||
if (frmWebBrowser != null && frmWebBrowser.Parent != null && frmWebBrowser.Parent.Parent != null && frmWebBrowser.Parent.Parent is BaseForm baseForm)
|
||||
{
|
||||
if (baseForm.InvokeRequired)
|
||||
{
|
||||
baseForm.Invoke(new Action(() =>
|
||||
{
|
||||
baseForm.Close();
|
||||
}));
|
||||
}
|
||||
else
|
||||
var browserControl = frmWebBrowser;
|
||||
PostToUiThread(
|
||||
browserControl,
|
||||
delegate
|
||||
{
|
||||
// Resolve the owning form only after returning to the
|
||||
// WinForms UI thread.
|
||||
var parent = browserControl.Parent;
|
||||
var baseForm = parent == null
|
||||
? null
|
||||
: parent.Parent as BaseForm;
|
||||
if (baseForm == null || baseForm.IsDisposed)
|
||||
return;
|
||||
|
||||
baseForm.Close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return base.OnProcessMessageReceived(browser, frame, sourceProcess, message);
|
||||
}
|
||||
|
||||
private static void PostToUiThread(
|
||||
System.Windows.Forms.Control control,
|
||||
Action action)
|
||||
{
|
||||
if (control == null || action == null || control.IsDisposed ||
|
||||
!control.IsHandleCreated)
|
||||
return;
|
||||
|
||||
Action guardedAction = delegate
|
||||
{
|
||||
if (control.IsDisposed)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ReportProcessMessageFailure(exception);
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// Never keep CEF's UI thread blocked while WinForms opens a
|
||||
// modal module that may create another CEF browser.
|
||||
control.BeginInvoke(guardedAction);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ReportProcessMessageFailure(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReportProcessMessageFailure(Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogHelper.Instance.WriteError(exception);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Never propagate logging failures into a native CEF callback.
|
||||
}
|
||||
|
||||
Action showError = delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageUtil.Show(exception);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
System.Windows.Forms.Control mainControl = ERPInfo.Instance.MainControl;
|
||||
if (mainControl == null || mainControl.IsDisposed ||
|
||||
!mainControl.IsHandleCreated)
|
||||
return;
|
||||
|
||||
if (mainControl.InvokeRequired)
|
||||
mainControl.BeginInvoke(showError);
|
||||
else
|
||||
showError();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// The main window may close while the callback is reporting.
|
||||
}
|
||||
}
|
||||
|
||||
public void Created(CefBrowser cefBrowser)
|
||||
{
|
||||
if (OnCreated != null)
|
||||
if (frmWebBrowser != null && OnCreated != null)
|
||||
{
|
||||
OnCreated(cefBrowser, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Closing(CefBrowser browser)
|
||||
{
|
||||
var control = frmWebBrowser;
|
||||
return control != null && control.BrowserClosing(browser);
|
||||
}
|
||||
|
||||
public void Closed(CefBrowser browser)
|
||||
{
|
||||
var control = frmWebBrowser;
|
||||
if (control != null)
|
||||
{
|
||||
control.BrowserClosed(browser);
|
||||
if (control.cefBrowserSettings == null)
|
||||
{
|
||||
frmWebBrowser = null;
|
||||
OnCreated = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,20 @@ namespace Lskj.Control.BrowserSetting2
|
||||
base.OnAfterCreated(browser);
|
||||
BsClient.Created(browser);
|
||||
}
|
||||
|
||||
protected override bool DoClose(CefBrowser browser)
|
||||
{
|
||||
// CEF sends WM_CLOSE to the parked application-owned host after
|
||||
// this callback. The host only allows that second close attempt.
|
||||
return BsClient.Closing(browser);
|
||||
}
|
||||
|
||||
protected override void OnBeforeClose(CefBrowser browser)
|
||||
{
|
||||
base.OnBeforeClose(browser);
|
||||
|
||||
// Release owner references after CEF completes its async close.
|
||||
BsClient.Closed(browser);
|
||||
}
|
||||
|
||||
protected override bool OnBeforePopup(
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xilium.CefGlue;
|
||||
using Lskj.Business;
|
||||
|
||||
namespace Lskj.Control.BrowserSetting2
|
||||
{
|
||||
@@ -46,7 +47,9 @@ namespace Lskj.Control.BrowserSetting2
|
||||
|
||||
protected override void OnRenderProcessTerminated(CefBrowser browser, CefTerminationStatus status)
|
||||
{
|
||||
browser.Reload();
|
||||
// Do not start a new renderer during native teardown.
|
||||
LogUtil.WriteError("CEF 渲染进程已终止,状态=" + status,
|
||||
new InvalidOperationException("CEF renderer termination status=" + status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+2
@@ -14,6 +14,8 @@ namespace Lskj.Control
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
CloseBrowserForDispose();
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
|
||||
@@ -109,6 +109,45 @@ namespace Lskj.Control
|
||||
cefBrowserSettings.GetMainFrame().LoadUrl(webResponse.ResponseUri.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool BrowserClosing(CefBrowser browser)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void BrowserClosed(CefBrowser browser)
|
||||
{
|
||||
var currentBrowser = cefBrowserSettings;
|
||||
if (currentBrowser == null || browser == null)
|
||||
return;
|
||||
|
||||
bool sameBrowser = ReferenceEquals(currentBrowser, browser);
|
||||
if (!sameBrowser)
|
||||
{
|
||||
try
|
||||
{
|
||||
sameBrowser = currentBrowser.IsSame(browser);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (sameBrowser)
|
||||
Interlocked.CompareExchange(ref cefBrowserSettings, null, currentBrowser);
|
||||
}
|
||||
|
||||
internal void CloseBrowser()
|
||||
{
|
||||
var browser = cefBrowserSettings;
|
||||
if (browser != null)
|
||||
browser.GetHost().CloseBrowser();
|
||||
}
|
||||
|
||||
private void CloseBrowserForDispose()
|
||||
{
|
||||
}
|
||||
|
||||
public static string ToEnUrl(string url)
|
||||
{
|
||||
string[] urlParams = url.Split('?');
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ namespace Lskj.Control
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
CloseBrowserForDispose();
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
|
||||
@@ -126,6 +126,45 @@ namespace Lskj.Control
|
||||
cefBrowserSettings.GetMainFrame().LoadUrl(webResponse.ResponseUri.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool BrowserClosing(CefBrowser browser)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void BrowserClosed(CefBrowser browser)
|
||||
{
|
||||
var currentBrowser = cefBrowserSettings;
|
||||
if (currentBrowser == null || browser == null)
|
||||
return;
|
||||
|
||||
bool sameBrowser = ReferenceEquals(currentBrowser, browser);
|
||||
if (!sameBrowser)
|
||||
{
|
||||
try
|
||||
{
|
||||
sameBrowser = currentBrowser.IsSame(browser);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (sameBrowser)
|
||||
Interlocked.CompareExchange(ref cefBrowserSettings, null, currentBrowser);
|
||||
}
|
||||
|
||||
internal void CloseBrowser()
|
||||
{
|
||||
var browser = cefBrowserSettings;
|
||||
if (browser != null)
|
||||
browser.GetHost().CloseBrowser();
|
||||
}
|
||||
|
||||
private void CloseBrowserForDispose()
|
||||
{
|
||||
}
|
||||
|
||||
public static string ToEnUrl(string url)
|
||||
{
|
||||
string[] urlParams = url.Split('?');
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Lskj.Control
|
||||
private bool mExtendedReturnDisplayEventAttached;
|
||||
private bool mExtendedReturnEditEventAttached;
|
||||
private bool mExtendedReturnDisposeEventAttached;
|
||||
private volatile bool mExtendedReturnDisposed;
|
||||
private int mExtendedReturnSchemaGeneration;
|
||||
|
||||
private sealed class ExtendedLookupRequestState
|
||||
@@ -62,6 +63,9 @@ namespace Lskj.Control
|
||||
{
|
||||
public GridColumnModel Model;
|
||||
public ExtendedReturnSearchPopup Popup;
|
||||
public PopupContainerControl PopupControl;
|
||||
public RepositoryItemPopupContainerEdit SearchEdit;
|
||||
public RepositoryItemTextEdit DisplayEdit;
|
||||
public PopupContainerEdit OwnerEdit;
|
||||
public DataRow BusinessRow;
|
||||
}
|
||||
@@ -124,7 +128,7 @@ namespace Lskj.Control
|
||||
|
||||
private void GridControlEx_Disposed_ExtendedReturn(object sender, EventArgs e)
|
||||
{
|
||||
DisposeExtendedReturnRequestTimers();
|
||||
DisposeExtendedReturnResources();
|
||||
}
|
||||
|
||||
private void InitExtendedSearchReturn(GridColumn column, GridColumnModel model)
|
||||
@@ -138,6 +142,8 @@ namespace Lskj.Control
|
||||
column.ColumnEdit = displayEdit;
|
||||
column.FilterMode = ColumnFilterMode.DisplayText;
|
||||
mExtendedReturnSearchEditors[model.FieldName] = searchEdit;
|
||||
ExtendedReturnPopupContext context = GetExtendedReturnPopupContext(model.FieldName);
|
||||
context.DisplayEdit = displayEdit;
|
||||
this.mControlList.Add(model);
|
||||
|
||||
if (!mExtendedReturnEditEventAttached)
|
||||
@@ -150,6 +156,14 @@ namespace Lskj.Control
|
||||
|
||||
private RepositoryItemPopupContainerEdit CreateExtendedReturnSearchEdit(GridColumnModel model)
|
||||
{
|
||||
ExtendedReturnPopupContext previousContext;
|
||||
if (mExtendedReturnPopupContexts.TryGetValue(model.FieldName, out previousContext))
|
||||
{
|
||||
mExtendedReturnPopupContexts.Remove(model.FieldName);
|
||||
mExtendedReturnSearchEditors.Remove(model.FieldName);
|
||||
DisposeExtendedReturnPopupContext(previousContext);
|
||||
}
|
||||
|
||||
Size popupSize = GetExtendedReturnPopupSize(model);
|
||||
ExtendedReturnSearchPopup popup = new ExtendedReturnSearchPopup();
|
||||
popup.Dock = DockStyle.Fill;
|
||||
@@ -185,7 +199,9 @@ namespace Lskj.Control
|
||||
ExtendedReturnPopupContext context = new ExtendedReturnPopupContext
|
||||
{
|
||||
Model = model,
|
||||
Popup = popup
|
||||
Popup = popup,
|
||||
PopupControl = popupControl,
|
||||
SearchEdit = searchEdit
|
||||
};
|
||||
popupControl.Tag = context;
|
||||
popup.Tag = context;
|
||||
@@ -662,6 +678,8 @@ namespace Lskj.Control
|
||||
string searchField,
|
||||
bool schemaOnly)
|
||||
{
|
||||
if (mExtendedReturnDisposed) return;
|
||||
|
||||
GridColumnModel model = context.Model;
|
||||
ExtendedLookupRequest request;
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
@@ -713,6 +731,8 @@ namespace Lskj.Control
|
||||
|
||||
private void ExtendedReturnDebounceElapsed(object stateValue)
|
||||
{
|
||||
if (mExtendedReturnDisposed) return;
|
||||
|
||||
string fieldName = stateValue as string;
|
||||
if (string.IsNullOrWhiteSpace(fieldName)) return;
|
||||
|
||||
@@ -723,6 +743,8 @@ namespace Lskj.Control
|
||||
|
||||
private void StartExtendedReturnWorker(string fieldName)
|
||||
{
|
||||
if (mExtendedReturnDisposed) return;
|
||||
|
||||
ExtendedLookupRequest request;
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
{
|
||||
@@ -750,6 +772,8 @@ namespace Lskj.Control
|
||||
{
|
||||
while (request != null)
|
||||
{
|
||||
if (mExtendedReturnDisposed) return;
|
||||
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
{
|
||||
ExtendedLookupRequestState currentState = GetExtendedLookupState(request.FieldName);
|
||||
@@ -761,6 +785,8 @@ namespace Lskj.Control
|
||||
}
|
||||
|
||||
ExtendedLookupQueryResult result = QueryExtendedReturn(request);
|
||||
if (mExtendedReturnDisposed) return;
|
||||
|
||||
bool deliverResult = false;
|
||||
ExtendedLookupRequest nextRequest = null;
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
@@ -928,11 +954,11 @@ namespace Lskj.Control
|
||||
|
||||
private void BeginInvokeExtendedReturnResult(ExtendedLookupRequest request, ExtendedLookupQueryResult result)
|
||||
{
|
||||
if (this.IsDisposed || !this.IsHandleCreated) return;
|
||||
if (mExtendedReturnDisposed || this.IsDisposed || !this.IsHandleCreated) return;
|
||||
|
||||
MethodInvoker deliver = new MethodInvoker(delegate
|
||||
{
|
||||
if (this.IsDisposed || request.Editor == null || request.Editor.IsDisposed) return;
|
||||
if (mExtendedReturnDisposed || this.IsDisposed || request.Editor == null || request.Editor.IsDisposed) return;
|
||||
if (!object.ReferenceEquals(this.GridView.ActiveEditor, request.Editor)) return;
|
||||
if (this.GridView.FocusedColumn == null ||
|
||||
!string.Equals(this.GridView.FocusedColumn.FieldName, request.FieldName, StringComparison.OrdinalIgnoreCase)) return;
|
||||
@@ -1286,6 +1312,8 @@ namespace Lskj.Control
|
||||
/// </summary>
|
||||
private void ResetExtendedReturnState()
|
||||
{
|
||||
if (mExtendedReturnDisposed) return;
|
||||
|
||||
DisposeExtendedReturnRequestTimers();
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
{
|
||||
@@ -1309,6 +1337,7 @@ namespace Lskj.Control
|
||||
state.Version++;
|
||||
state.DeliveredVersion = 0;
|
||||
state.PendingRequest = null;
|
||||
state.IsRunning = false;
|
||||
if (state.DebounceTimer != null)
|
||||
{
|
||||
state.DebounceTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
@@ -1318,5 +1347,163 @@ namespace Lskj.Control
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放扩展返回专用的弹窗控件树和事件订阅。
|
||||
/// PopupContainerControl 不在 GridControlEx.Controls 树中,不能依赖宿主控件的
|
||||
/// 默认 Dispose 递归释放;这里必须显式切断事件和 GridView 的本地化器订阅。
|
||||
/// </summary>
|
||||
private void DisposeExtendedReturnResources()
|
||||
{
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
{
|
||||
if (mExtendedReturnDisposed) return;
|
||||
mExtendedReturnDisposed = true;
|
||||
}
|
||||
|
||||
DisposeExtendedReturnRequestTimers();
|
||||
|
||||
try
|
||||
{
|
||||
if (mExtendedReturnDisplayEventAttached)
|
||||
{
|
||||
this.GridView.CustomColumnDisplayText -= GridView_CustomColumnDisplayText_ExtendedReturn;
|
||||
mExtendedReturnDisplayEventAttached = false;
|
||||
}
|
||||
if (mExtendedReturnEditEventAttached)
|
||||
{
|
||||
this.GridView.CustomRowCellEditForEditing -= GridView_CustomRowCellEditForEditing_ExtendedReturn;
|
||||
this.GridView.RowCellClick -= GridView_RowCellClick_ExtendedReturn;
|
||||
mExtendedReturnEditEventAttached = false;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 宿主 GridView 可能已经进入 DevExpress 的销毁流程,释放必须继续。
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Disposed -= GridControlEx_Disposed_ExtendedReturn;
|
||||
mExtendedReturnDisposeEventAttached = false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
List<ExtendedReturnPopupContext> contexts =
|
||||
new List<ExtendedReturnPopupContext>(mExtendedReturnPopupContexts.Values);
|
||||
List<RepositoryItemPopupContainerEdit> searchEditors =
|
||||
new List<RepositoryItemPopupContainerEdit>(mExtendedReturnSearchEditors.Values);
|
||||
|
||||
mExtendedReturnPopupContexts.Clear();
|
||||
mExtendedReturnSearchEditors.Clear();
|
||||
|
||||
foreach (ExtendedReturnPopupContext context in contexts)
|
||||
{
|
||||
DisposeExtendedReturnPopupContext(context);
|
||||
}
|
||||
|
||||
// 防止异常配置导致某个 editor 没有对应 context 时仍然遗留事件订阅。
|
||||
foreach (RepositoryItemPopupContainerEdit searchEdit in searchEditors)
|
||||
{
|
||||
DisposeExtendedReturnSearchEditor(searchEdit);
|
||||
}
|
||||
|
||||
lock (mExtendedReturnSyncRoot)
|
||||
{
|
||||
foreach (DataTable schema in mExtendedReturnSchemas.Values)
|
||||
{
|
||||
DisposeExtendedReturnDataTable(schema);
|
||||
}
|
||||
mExtendedReturnSchemas.Clear();
|
||||
mExtendedReturnSchemaSqls.Clear();
|
||||
mExtendedReturnQueryStates.Clear();
|
||||
mExtendedReturnSchemaGeneration++;
|
||||
}
|
||||
mExtendedReturnDisplayFields.Clear();
|
||||
|
||||
// 这些字段会在扩展返回弹窗操作中指向当前 GridView,销毁时不能继续保留引用。
|
||||
CurrentOperGridView = null;
|
||||
CurrentOperModel = null;
|
||||
CurrentOperColumnKey = string.Empty;
|
||||
}
|
||||
|
||||
private void DisposeExtendedReturnPopupContext(ExtendedReturnPopupContext context)
|
||||
{
|
||||
if (context == null) return;
|
||||
|
||||
PopupContainerEdit ownerEdit = context.OwnerEdit;
|
||||
if (ownerEdit != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ownerEdit.IsDisposed && ownerEdit.IsPopupOpen)
|
||||
{
|
||||
ownerEdit.ClosePopup();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedReturnSearchPopup popup = context.Popup;
|
||||
if (popup != null)
|
||||
{
|
||||
try { popup.SearchRequested -= ExtendedReturnSearch_SearchRequested; } catch { }
|
||||
try { popup.ClearRequested -= ExtendedReturnSearch_ClearRequested; } catch { }
|
||||
try { popup.ResultSelected -= ExtendedReturnSearch_ResultSelected; } catch { }
|
||||
try { popup.ResultGrid.DataSource = null; } catch { }
|
||||
try { popup.ClearResultAndFilter(); } catch { }
|
||||
try { popup.Tag = null; } catch { }
|
||||
}
|
||||
|
||||
PopupContainerControl popupControl = context.PopupControl;
|
||||
if (popupControl != null)
|
||||
{
|
||||
try { popupControl.Tag = null; } catch { }
|
||||
}
|
||||
|
||||
DisposeExtendedReturnSearchEditor(context.SearchEdit);
|
||||
DisposeExtendedReturnComponent(popup == null ? null : popup.ResultView);
|
||||
DisposeExtendedReturnComponent(popup == null ? null : popup.ResultGrid);
|
||||
DisposeExtendedReturnComponent(popup);
|
||||
DisposeExtendedReturnComponent(popupControl);
|
||||
DisposeExtendedReturnComponent(context.DisplayEdit);
|
||||
|
||||
context.Model = null;
|
||||
context.Popup = null;
|
||||
context.PopupControl = null;
|
||||
context.SearchEdit = null;
|
||||
context.DisplayEdit = null;
|
||||
context.OwnerEdit = null;
|
||||
context.BusinessRow = null;
|
||||
}
|
||||
|
||||
private void DisposeExtendedReturnSearchEditor(RepositoryItemPopupContainerEdit searchEdit)
|
||||
{
|
||||
if (searchEdit == null) return;
|
||||
|
||||
try { searchEdit.QueryPopUp -= ExtendedReturnSearch_QueryPopUp; } catch { }
|
||||
try { searchEdit.Popup -= ExtendedReturnSearch_Popup; } catch { }
|
||||
try { searchEdit.Closed -= ExtendedReturnSearch_Closed; } catch { }
|
||||
try { searchEdit.QueryDisplayText -= ExtendedReturnSearch_QueryDisplayText; } catch { }
|
||||
try { searchEdit.PopupControl = null; } catch { }
|
||||
try { searchEdit.Tag = null; } catch { }
|
||||
DisposeExtendedReturnComponent(searchEdit);
|
||||
}
|
||||
|
||||
private static void DisposeExtendedReturnDataTable(DataTable table)
|
||||
{
|
||||
if (table == null) return;
|
||||
try { table.Dispose(); } catch { }
|
||||
}
|
||||
|
||||
private static void DisposeExtendedReturnComponent(IDisposable component)
|
||||
{
|
||||
if (component == null) return;
|
||||
try { component.Dispose(); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,6 +564,71 @@ namespace Lskj.Control
|
||||
this.gridView.MouseWheel += GridView_MouseWheel;
|
||||
}
|
||||
|
||||
private DbCommandBuilder _adapterCommandBuilder;
|
||||
|
||||
protected static void DisposeDataAdapter(DbDataAdapter adapter)
|
||||
{
|
||||
if (adapter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DbCommand[] commands =
|
||||
{
|
||||
adapter.SelectCommand,
|
||||
adapter.InsertCommand,
|
||||
adapter.UpdateCommand,
|
||||
adapter.DeleteCommand
|
||||
};
|
||||
|
||||
foreach (DbCommand command in commands)
|
||||
{
|
||||
try
|
||||
{
|
||||
command?.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Resource cleanup must not break control disposal or a new query.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
adapter.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Resource cleanup must not break control disposal or a new query.
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetAdapterCommandBuilder(DbDataAdapter adapter)
|
||||
{
|
||||
DisposeAdapterCommandBuilder();
|
||||
if (adapter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_adapterCommandBuilder = SqlHelper.dbFactory.CreateCommandBuilder();
|
||||
_adapterCommandBuilder.DataAdapter = adapter;
|
||||
}
|
||||
|
||||
protected void DisposeAdapterCommandBuilder()
|
||||
{
|
||||
DbCommandBuilder commandBuilder = _adapterCommandBuilder;
|
||||
_adapterCommandBuilder = null;
|
||||
try
|
||||
{
|
||||
commandBuilder?.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Resource cleanup must not break control disposal or a new query.
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeGridResources()
|
||||
{
|
||||
if (_gridResourcesDisposed)
|
||||
@@ -578,9 +643,23 @@ namespace Lskj.Control
|
||||
mTimer.Dispose();
|
||||
mTimer = null;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (GridControl != null)
|
||||
{
|
||||
GridControl.DataSource = null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// The inner DevExpress control may already be disposed.
|
||||
}
|
||||
DisposeColumnImageCaches(ColumnList);
|
||||
DisposeRightMenuButtonImages();
|
||||
ClearBarcodeImageCache();
|
||||
DisposeAdapterCommandBuilder();
|
||||
DisposeDataAdapter(AdapterObj);
|
||||
AdapterObj = null;
|
||||
mControlSourceDic.Clear();
|
||||
mControlList.Clear();
|
||||
ColumnList.Clear();
|
||||
@@ -589,6 +668,9 @@ namespace Lskj.Control
|
||||
ImageList.Clear();
|
||||
RepeatedVerificationNames.Clear();
|
||||
PromptMessage.Clear();
|
||||
ParentControl = null;
|
||||
Model = null;
|
||||
SysModel = null;
|
||||
if (_mainGridToolTipController != null)
|
||||
{
|
||||
_mainGridToolTipController.BeforeShow -= MainGvTool_BeforeShow;
|
||||
@@ -599,6 +681,11 @@ namespace Lskj.Control
|
||||
_mainGridToolTipController.Dispose();
|
||||
_mainGridToolTipController = null;
|
||||
}
|
||||
if (customFont != null)
|
||||
{
|
||||
customFont.Dispose();
|
||||
customFont = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareForColumnRebuild()
|
||||
@@ -2036,7 +2123,7 @@ namespace Lskj.Control
|
||||
//}));
|
||||
Task<DataTable> customColumnByDatabaseTask = cachesDic.AddTask(this, "CustomColumnByDatabase", new Task<DataTable>(() =>
|
||||
{
|
||||
return this.GridView.GetCustomColumnByDatabase(customColumKey);
|
||||
return GridExtend.GetCustomColumnByDatabase(customColumKey);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -2171,12 +2258,14 @@ namespace Lskj.Control
|
||||
{
|
||||
if (adapter == null) return 0;
|
||||
|
||||
DbDataAdapter previousAdapter = this.AdapterObj;
|
||||
bool adapterAssigned = false;
|
||||
DataSet dataSet = null;
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
this.AdapterObj = adapter;
|
||||
DataSet dataSet = new DataSet();
|
||||
dataSet = new DataSet();
|
||||
|
||||
// 重连配置
|
||||
int maxRetryCount = 2; // 次数
|
||||
@@ -2215,7 +2304,23 @@ namespace Lskj.Control
|
||||
}
|
||||
}
|
||||
|
||||
DataTable dt = dataSet.Tables.Count > 0 ? dataSet.Tables[0] : null;
|
||||
int rowCount = dt == null ? 0 : dt.Rows.Count;
|
||||
if (dt != null)
|
||||
{
|
||||
// Detach the result table before releasing the temporary DataSet.
|
||||
dataSet.Tables.Remove(dt);
|
||||
}
|
||||
dataSet.Dispose();
|
||||
dataSet = null;
|
||||
|
||||
DisposeAdapterCommandBuilder();
|
||||
if (previousAdapter != null && !ReferenceEquals(previousAdapter, adapter))
|
||||
{
|
||||
DisposeDataAdapter(previousAdapter);
|
||||
}
|
||||
this.AdapterObj = adapter;
|
||||
adapterAssigned = true;
|
||||
|
||||
if (this.ColumnList == null || this.ColumnList.Count == 0)
|
||||
{
|
||||
@@ -2230,12 +2335,10 @@ namespace Lskj.Control
|
||||
this.gridView.Columns.Clear();
|
||||
}
|
||||
}
|
||||
DbCommandBuilder cb = SqlHelper.dbFactory.CreateCommandBuilder();
|
||||
cb.DataAdapter = this.AdapterObj;
|
||||
SetAdapterCommandBuilder(this.AdapterObj);
|
||||
//this.GridControl.DataSource = dataSet.Tables[0];
|
||||
|
||||
//解决大小写问题后在赋值
|
||||
DataTable dt = dataSet.Tables[0];
|
||||
if (dt != null && this.gridView.Columns.Count > 0)
|
||||
{
|
||||
foreach (DataColumn column in dt.Columns)
|
||||
@@ -2276,12 +2379,20 @@ namespace Lskj.Control
|
||||
this.SetAutoColumns();
|
||||
if (selectRowHandler)
|
||||
this.gridView.SelectRowHandler(this.gridView.FocusedRowHandle);
|
||||
return dataSet.Tables[0] != null ? dataSet.Tables[0].Rows.Count : 0;
|
||||
return rowCount;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!adapterAssigned)
|
||||
{
|
||||
DisposeDataAdapter(adapter);
|
||||
}
|
||||
MessageUtil.Show(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
dataSet?.Dispose();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5536,9 +5647,7 @@ namespace Lskj.Control
|
||||
/// <param name="e">事件参数。</param>
|
||||
private void OnGridControlExDisposed(object sender, EventArgs e)
|
||||
{
|
||||
if (_gridResourcesDisposed) return;
|
||||
_gridResourcesDisposed = true;
|
||||
|
||||
DisposeGridResources();
|
||||
foreach (FrmModelLookUp2 modelLookUp in selectReturnModelLookUpCache.Values.Distinct())
|
||||
{
|
||||
if (modelLookUp != null && !modelLookUp.IsDisposed)
|
||||
@@ -5548,19 +5657,6 @@ namespace Lskj.Control
|
||||
}
|
||||
selectReturnModelLookUpCache.Clear();
|
||||
selectReturnDisplaySourceCache.Clear();
|
||||
|
||||
if (_mainGridToolTipController != null)
|
||||
{
|
||||
_mainGridToolTipController.BeforeShow -= MainGvTool_BeforeShow;
|
||||
_mainGridToolTipController.Dispose();
|
||||
_mainGridToolTipController = null;
|
||||
}
|
||||
|
||||
if (customFont != null)
|
||||
{
|
||||
customFont.Dispose();
|
||||
customFont = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -456,6 +456,7 @@
|
||||
<Compile Include="BlinkBrowser.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="CefBrowserLifetimeCoordinator.cs" />
|
||||
<Compile Include="BrowserSetting2\BsClient.cs" />
|
||||
<Compile Include="BrowserSetting2\BsContextMenuHandler.cs" />
|
||||
<Compile Include="BrowserSetting2\BsDownloadHandler.cs" />
|
||||
|
||||
@@ -29,6 +29,65 @@ namespace Lskj.Control.Model
|
||||
public class BandedGridDragGrid : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
internal static void DisposeRegistrations(
|
||||
Dictionary<BandedGridView, List<BandedGridDragGrid>> sourceRegistrations,
|
||||
Dictionary<GridView, List<BandedGridDragGrid>> targetRegistrations,
|
||||
BandedGridView sourceGridView,
|
||||
GridView targetGridView)
|
||||
{
|
||||
DisposeSourceRegistrations(sourceRegistrations, sourceGridView);
|
||||
DisposeTargetRegistrations(targetRegistrations, targetGridView);
|
||||
}
|
||||
|
||||
private static void DisposeSourceRegistrations(
|
||||
Dictionary<BandedGridView, List<BandedGridDragGrid>> registrations,
|
||||
BandedGridView gridView)
|
||||
{
|
||||
foreach (KeyValuePair<BandedGridView, List<BandedGridDragGrid>> entry in registrations.ToList())
|
||||
{
|
||||
bool removeKey = ReferenceEquals(entry.Key, gridView);
|
||||
foreach (BandedGridDragGrid registration in entry.Value.ToList())
|
||||
{
|
||||
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
|
||||
{
|
||||
if (registration != null)
|
||||
registration.Dispose();
|
||||
entry.Value.Remove(registration);
|
||||
}
|
||||
}
|
||||
if (removeKey || entry.Value.Count == 0)
|
||||
registrations.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DisposeTargetRegistrations(
|
||||
Dictionary<GridView, List<BandedGridDragGrid>> registrations,
|
||||
GridView gridView)
|
||||
{
|
||||
foreach (KeyValuePair<GridView, List<BandedGridDragGrid>> entry in registrations.ToList())
|
||||
{
|
||||
bool removeKey = ReferenceEquals(entry.Key, gridView);
|
||||
foreach (BandedGridDragGrid registration in entry.Value.ToList())
|
||||
{
|
||||
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
|
||||
{
|
||||
if (registration != null)
|
||||
registration.Dispose();
|
||||
entry.Value.Remove(registration);
|
||||
}
|
||||
}
|
||||
if (removeKey || entry.Value.Count == 0)
|
||||
registrations.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool References(GridView gridView)
|
||||
{
|
||||
return gridView != null &&
|
||||
(ReferenceEquals(_sourceGridView, gridView) ||
|
||||
ReferenceEquals(_targetGridView, gridView));
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否正在拖拽
|
||||
/// </summary>
|
||||
|
||||
@@ -32,6 +32,43 @@ namespace Lskj.Control.Model
|
||||
public class GridDragGrid : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
internal static void DisposeRegistrations(
|
||||
Dictionary<GridView, List<GridDragGrid>> sourceRegistrations,
|
||||
Dictionary<GridView, List<GridDragGrid>> targetRegistrations,
|
||||
GridView gridView)
|
||||
{
|
||||
DisposeRegistrations(sourceRegistrations, gridView);
|
||||
DisposeRegistrations(targetRegistrations, gridView);
|
||||
}
|
||||
|
||||
private static void DisposeRegistrations(
|
||||
Dictionary<GridView, List<GridDragGrid>> registrations,
|
||||
GridView gridView)
|
||||
{
|
||||
foreach (KeyValuePair<GridView, List<GridDragGrid>> entry in registrations.ToList())
|
||||
{
|
||||
bool removeKey = ReferenceEquals(entry.Key, gridView);
|
||||
foreach (GridDragGrid registration in entry.Value.ToList())
|
||||
{
|
||||
if (removeKey || registration == null || registration._disposed || registration.References(gridView))
|
||||
{
|
||||
if (registration != null)
|
||||
registration.Dispose();
|
||||
entry.Value.Remove(registration);
|
||||
}
|
||||
}
|
||||
if (removeKey || entry.Value.Count == 0)
|
||||
registrations.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool References(GridView gridView)
|
||||
{
|
||||
return gridView != null &&
|
||||
(ReferenceEquals(_sourceGridView, gridView) ||
|
||||
ReferenceEquals(_targetGridView, gridView));
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否正在拖拽
|
||||
/// </summary>
|
||||
|
||||
@@ -101,7 +101,6 @@ namespace Lskj.Control.Model
|
||||
_gridView = null;
|
||||
_treeView = null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>说明:获取表格选中行数据</para>
|
||||
|
||||
@@ -913,6 +913,14 @@ namespace Lskj.Control.Model
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>DataTable.</returns>
|
||||
public static DataTable GetCustomColumnByDatabase(this GridView gridView, string key)
|
||||
{
|
||||
return GetCustomColumnByDatabase(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取个性配置列数据,不依赖任何界面控件。
|
||||
/// </summary>
|
||||
public static DataTable GetCustomColumnByDatabase(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -954,18 +962,7 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
BaseImpl.ExecSqlValue("alter table " + ResourceKeys.SettingTableName + " add IfFixColumn bit");
|
||||
}
|
||||
// 读取普通用户读取个人配置,没有则读取管理员配置,管理未配置则读取系统默认.逐级上报读取方式.
|
||||
string sqlValue = string.Format("select * from {0} where formKey='{1}' and operatorid='{2}' order by orderid ", ResourceKeys.SettingTableName, key, ERPInfo.Instance.UserId);
|
||||
|
||||
DataTable table = BaseImpl.GetDataTableResult(sqlValue);
|
||||
|
||||
//if (table == null || table.Rows.Count == 0)
|
||||
//{
|
||||
// sqlValue = string.Format("select * from {0} where formKey='{1}' and operatorid='{2}'", ResourceKeys.SettingTableName, key, ERPInfo.Instance.UserManager);
|
||||
// table = BaseImpl.GetDataTableResult(sqlValue);
|
||||
//}
|
||||
|
||||
return table;
|
||||
return GetCustomColumnByDatabase(key);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -32,8 +32,10 @@ namespace Lskj.Control.Model
|
||||
/// <summary>
|
||||
/// 查询控件、添加修改界面控件管理类
|
||||
/// </summary>
|
||||
public class MyControl
|
||||
public class MyControl : IDisposable
|
||||
{
|
||||
private const long UserSearchCooldownTicks =
|
||||
TimeSpan.TicksPerMillisecond * 350;
|
||||
private string _searchSql;
|
||||
private DataTable _controls;
|
||||
private DataTable _schemes;
|
||||
@@ -46,8 +48,12 @@ namespace Lskj.Control.Model
|
||||
private GridControlEx _gridLeft;
|
||||
private TreeViewEx _tvLeft;
|
||||
private MyControl _leftSearch;
|
||||
private DropDownButton _dropDown = new DropDownButton();
|
||||
private PopupMenu _popupMenu = new PopupMenu();
|
||||
private DropDownButton _dropDown;
|
||||
private PopupMenu _popupMenu;
|
||||
private bool mDisposed;
|
||||
private bool mUserSearchInProgress;
|
||||
private long mLastUserSearchCompletedTicks;
|
||||
private int mAcceptedUserSearchCount;
|
||||
/// <summary>
|
||||
/// 计算字段
|
||||
/// </summary>
|
||||
@@ -112,6 +118,10 @@ namespace Lskj.Control.Model
|
||||
/// </summary>
|
||||
/// <value>The button object.</value>
|
||||
public SimpleButton ButtonObj { get { return _button; } }
|
||||
public int AcceptedUserSearchCount
|
||||
{
|
||||
get { return mAcceptedUserSearchCount; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 条件数据源刷新按钮
|
||||
/// </summary>
|
||||
@@ -1031,6 +1041,10 @@ namespace Lskj.Control.Model
|
||||
// 创建模版搜索
|
||||
if (_schemes != null && ModuleId > 0 && _schemes.Rows.Count > 0)
|
||||
{
|
||||
if (_popupMenu == null)
|
||||
{
|
||||
_popupMenu = new PopupMenu();
|
||||
}
|
||||
_dropDown = new DropDownButton();
|
||||
_dropDown.DropDownArrowStyle = DropDownArrowStyle.Show;
|
||||
_dropDown.DropDownControl = this._popupMenu;
|
||||
@@ -1222,6 +1236,10 @@ namespace Lskj.Control.Model
|
||||
// 创建模版搜索
|
||||
if (_schemes != null && ModuleId > 0 && _schemes.Rows.Count > 0)
|
||||
{
|
||||
if (_popupMenu == null)
|
||||
{
|
||||
_popupMenu = new PopupMenu();
|
||||
}
|
||||
_dropDown = new DropDownButton();
|
||||
_dropDown.DropDownArrowStyle = DropDownArrowStyle.Show;
|
||||
_dropDown.DropDownControl = this._popupMenu;
|
||||
@@ -1758,8 +1776,14 @@ namespace Lskj.Control.Model
|
||||
WaitForm.HideForm();
|
||||
mControlSourceDic.Clear();
|
||||
if (this.OnDataSourceBindCallBack != null) this.OnDataSourceBindCallBack(this, null);
|
||||
this.mTimer.Stop();
|
||||
this.mTimer.Dispose();
|
||||
Timer timer = this.mTimer;
|
||||
this.mTimer = null;
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Tick -= mTimerTick;
|
||||
timer.Stop();
|
||||
timer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6113,6 +6137,61 @@ namespace Lskj.Control.Model
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryBeginUserSearch()
|
||||
{
|
||||
if (mDisposed || mUserSearchInProgress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
long now = DateTime.UtcNow.Ticks;
|
||||
if (mLastUserSearchCompletedTicks > 0 &&
|
||||
now - mLastUserSearchCompletedTicks < UserSearchCooldownTicks)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mUserSearchInProgress = true;
|
||||
mAcceptedUserSearchCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void EndUserSearch()
|
||||
{
|
||||
mUserSearchInProgress = false;
|
||||
mLastUserSearchCompletedTicks = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
private bool ExecuteUserSearch(object sender, EventArgs e)
|
||||
{
|
||||
if (!TryBeginUserSearch())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SearchArgs args = new SearchArgs();
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
{
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
}
|
||||
if (args.Continue)
|
||||
{
|
||||
this.SearchGrid(false);
|
||||
}
|
||||
if (OnSearchAfterCallBack != null)
|
||||
{
|
||||
OnSearchAfterCallBack(sender, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndUserSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>说明:</para>
|
||||
/// <para>创建人:龚宇超</para>
|
||||
@@ -6137,18 +6216,8 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
if (baseControl.Model.IsSearchControl)
|
||||
{
|
||||
// 搜索控件回车直接搜索
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
|
||||
if (baseControl.Model.ScanAfterEmpty)
|
||||
if (ExecuteUserSearch(sender, e) &&
|
||||
baseControl.Model.ScanAfterEmpty)
|
||||
{
|
||||
baseControl.EditText = string.Empty;
|
||||
}
|
||||
@@ -6247,14 +6316,7 @@ namespace Lskj.Control.Model
|
||||
{
|
||||
if (baseControl.Model.IsSearchControl)
|
||||
{
|
||||
// 搜索控件回车直接搜索
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
ExecuteUserSearch(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6271,45 +6333,57 @@ namespace Lskj.Control.Model
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
protected void OnSimpleButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
if (!TryBeginUserSearch())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null)
|
||||
try
|
||||
{
|
||||
bool allowBefore = ApiHelper.IsExecEventApi(Interface.Api.OperateEvent.BeforeSearchBtnClick, Model.ModuleCode, 0);
|
||||
//查询前调用Api接口
|
||||
if (allowBefore)
|
||||
if (Model != null)
|
||||
{
|
||||
DataRow dataRow = this.GetAllControlValueRow();
|
||||
ApiHelper apiHelper = new ApiHelper(Model.ModuleCode, 0, dataRow);
|
||||
apiHelper.OnEvent(Interface.Api.OperateEvent.BeforeSearchBtnClick, Interface.Api.ActionType.None);
|
||||
if (apiHelper.apiHandlerModels.Count > 0)
|
||||
bool allowBefore = ApiHelper.IsExecEventApi(Interface.Api.OperateEvent.BeforeSearchBtnClick, Model.ModuleCode, 0);
|
||||
//查询前调用Api接口
|
||||
if (allowBefore)
|
||||
{
|
||||
Hashtable hashtable = apiHelper.apiHandlerModels[apiHelper.apiHandlerModels.Count - 1].resultPmsHashtables[0];
|
||||
if (hashtable.ContainsKey("result"))
|
||||
DataRow dataRow = this.GetAllControlValueRow();
|
||||
ApiHelper apiHelper = new ApiHelper(Model.ModuleCode, 0, dataRow);
|
||||
apiHelper.OnEvent(Interface.Api.OperateEvent.BeforeSearchBtnClick, Interface.Api.ActionType.None);
|
||||
if (apiHelper.apiHandlerModels.Count > 0)
|
||||
{
|
||||
string jsonResult = hashtable["result"] + "";
|
||||
DataTable dataTable = JsonConvert.DeserializeObject<DataTable>(jsonResult);
|
||||
this._mainGridEx.SetGridViewDataSource(dataTable);
|
||||
return;
|
||||
Hashtable hashtable = apiHelper.apiHandlerModels[apiHelper.apiHandlerModels.Count - 1].resultPmsHashtables[0];
|
||||
if (hashtable.ContainsKey("result"))
|
||||
{
|
||||
string jsonResult = hashtable["result"] + "";
|
||||
DataTable dataTable = JsonConvert.DeserializeObject<DataTable>(jsonResult);
|
||||
this._mainGridEx.SetGridViewDataSource(dataTable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageUtil.Show(ex.Message);
|
||||
}
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
finally
|
||||
{
|
||||
MessageUtil.Show(ex.Message);
|
||||
EndUserSearch();
|
||||
}
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
}
|
||||
|
||||
|
||||
@@ -6344,15 +6418,7 @@ namespace Lskj.Control.Model
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
protected void OnFixButtonClick(object sender, EventArgs e)
|
||||
{
|
||||
SearchArgs args = new SearchArgs();
|
||||
// 查询之前
|
||||
if (OnSearchBeforeCallBack != null)
|
||||
OnSearchBeforeCallBack(sender, args);
|
||||
|
||||
if (args.Continue) this.SearchGrid(false);
|
||||
|
||||
// 查询之后
|
||||
if (OnSearchAfterCallBack != null) OnSearchAfterCallBack(sender, e);
|
||||
ExecuteUserSearch(sender, e);
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>说明:高级搜索按钮鼠标离开时</para>
|
||||
@@ -6738,6 +6804,154 @@ namespace Lskj.Control.Model
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing || mDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDisposed = true;
|
||||
mUserSearchInProgress = false;
|
||||
|
||||
Timer timer = mTimer;
|
||||
mTimer = null;
|
||||
if (timer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
timer.Tick -= mTimerTick;
|
||||
timer.Stop();
|
||||
timer.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A completed delayed-load timer may already be disposed.
|
||||
}
|
||||
}
|
||||
|
||||
if (_button != null)
|
||||
{
|
||||
_button.Click -= OnSimpleButtonClick;
|
||||
_button.Tag = null;
|
||||
}
|
||||
if (_fixButton != null)
|
||||
{
|
||||
_fixButton.Click -= OnFixButtonClick;
|
||||
}
|
||||
if (_refreshButton != null)
|
||||
{
|
||||
_refreshButton.Click -= OnRefreshButtonClick;
|
||||
_refreshButton.Tag = null;
|
||||
}
|
||||
if (btnCondSearch != null)
|
||||
{
|
||||
btnCondSearch.Click -= OnBtnCondSearchClick;
|
||||
btnCondSearch.Tag = null;
|
||||
}
|
||||
if (_dropDown != null)
|
||||
{
|
||||
_dropDown.Leave -= OnDropDownLeave;
|
||||
_dropDown.DropDownControl = null;
|
||||
}
|
||||
foreach (SimpleButton button in mrpBtnDic.Values.Distinct())
|
||||
{
|
||||
if (button != null)
|
||||
{
|
||||
button.Click -= OnModuleClick;
|
||||
button.Tag = null;
|
||||
}
|
||||
}
|
||||
|
||||
BarManager searchSchemeManager =
|
||||
_popupMenu == null ? null : _popupMenu.Manager;
|
||||
if (_popupMenu != null)
|
||||
{
|
||||
_popupMenu.Manager = null;
|
||||
_popupMenu.ItemLinks.Clear();
|
||||
_popupMenu.Dispose();
|
||||
}
|
||||
if (searchSchemeManager != null)
|
||||
{
|
||||
searchSchemeManager.Dispose();
|
||||
}
|
||||
|
||||
if (_mainGridEx != null &&
|
||||
ReferenceEquals(_mainGridEx.ParentControl, this))
|
||||
{
|
||||
_mainGridEx.ParentControl = null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt module disposal.
|
||||
}
|
||||
|
||||
preSearchVerification = null;
|
||||
OnSearchBeforeCallBack = null;
|
||||
OnSearchAfterCallBack = null;
|
||||
OnAddCallBack = null;
|
||||
ClearDetails = null;
|
||||
OnLastQueryTriggered = null;
|
||||
OnSourceRefrshCallBack = null;
|
||||
OnDataSourceBindCallBack = null;
|
||||
OnDataFileRefrshCallBack = null;
|
||||
OpenDocumentSource = null;
|
||||
|
||||
_calcControls.Clear();
|
||||
_models.Clear();
|
||||
mControlList.Clear();
|
||||
mExtendedReturnSearchControls.Clear();
|
||||
mExtendedReturnPendingChanges.Clear();
|
||||
mControlSourceDic.Clear();
|
||||
mCacheDictionary.Clear();
|
||||
DetailSelection.Clear();
|
||||
changeLabelAutoGridLooks.Clear();
|
||||
mrpBtnDic.Clear();
|
||||
ModuleResultDic.Clear();
|
||||
ParaContrlsDic.Clear();
|
||||
|
||||
_controls = null;
|
||||
_schemes = null;
|
||||
_fixField = null;
|
||||
_fixKey = null;
|
||||
_button = null;
|
||||
_fixButton = null;
|
||||
_refreshButton = null;
|
||||
_dropDown = null;
|
||||
_popupMenu = null;
|
||||
btnCondSearch = null;
|
||||
_gridControl = null;
|
||||
_mainGridEx = null;
|
||||
_gridLeft = null;
|
||||
_tvLeft = null;
|
||||
_leftSearch = null;
|
||||
_parentPanel = null;
|
||||
CurrentData = null;
|
||||
SystemModel = null;
|
||||
SaveCondTab = null;
|
||||
mrpDyncModel = null;
|
||||
Model = null;
|
||||
popUpDyncModel = null;
|
||||
rightItemLinks = null;
|
||||
SpecialLeftTable = null;
|
||||
beforeData = null;
|
||||
OtherParams = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,94 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using WinFormsControl = System.Windows.Forms.Control;
|
||||
|
||||
namespace Lskj.Control.Model
|
||||
{
|
||||
public static class StaticBandedControl
|
||||
{
|
||||
public static void ReleaseModuleReferences(WinFormsControl moduleRoot, XtraTabPage modulePage, string moduleCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<BandedGridView> bandedViews = CollectBandedGridViews(moduleRoot);
|
||||
List<GridView> targetViews = CollectTargetGridViews(moduleRoot);
|
||||
foreach (BandedGridView view in bandedViews)
|
||||
BandedGridDragGrid.DisposeRegistrations(
|
||||
BandedGridViewDragGridDic,
|
||||
BandedTargetViewDragGridDic,
|
||||
view,
|
||||
null);
|
||||
foreach (GridView view in targetViews)
|
||||
BandedGridDragGrid.DisposeRegistrations(
|
||||
BandedGridViewDragGridDic,
|
||||
BandedTargetViewDragGridDic,
|
||||
null,
|
||||
view);
|
||||
if (SourceDragBandedGridView != null &&
|
||||
(bandedViews.Contains(SourceDragBandedGridView) ||
|
||||
(SourceDragBandedGridView.GridControl != null && SourceDragBandedGridView.GridControl.IsDisposed)))
|
||||
SourceDragBandedGridView = null;
|
||||
RemoveConditionPanels(moduleCode);
|
||||
while (modulePage != null && DogVerifyModuleForms.Remove(modulePage))
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("释放旧 Banded 模块引用失败:" + exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<BandedGridView> CollectBandedGridViews(WinFormsControl root)
|
||||
{
|
||||
List<BandedGridView> result = new List<BandedGridView>();
|
||||
if (root == null)
|
||||
return result;
|
||||
foreach (WinFormsControl control in EnumerateControls(root))
|
||||
{
|
||||
DevExpress.XtraGrid.GridControl grid = control as DevExpress.XtraGrid.GridControl;
|
||||
BandedGridView view = grid == null ? null : grid.MainView as BandedGridView;
|
||||
if (view != null && !result.Contains(view))
|
||||
result.Add(view);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<GridView> CollectTargetGridViews(WinFormsControl root)
|
||||
{
|
||||
List<GridView> result = new List<GridView>();
|
||||
if (root == null)
|
||||
return result;
|
||||
foreach (WinFormsControl control in EnumerateControls(root))
|
||||
{
|
||||
DevExpress.XtraGrid.GridControl grid = control as DevExpress.XtraGrid.GridControl;
|
||||
GridView view = grid == null ? null : grid.MainView as GridView;
|
||||
if (view != null && !result.Contains(view))
|
||||
result.Add(view);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<WinFormsControl> EnumerateControls(WinFormsControl root)
|
||||
{
|
||||
yield return root;
|
||||
foreach (WinFormsControl child in root.Controls)
|
||||
foreach (WinFormsControl nested in EnumerateControls(child))
|
||||
yield return nested;
|
||||
}
|
||||
|
||||
private static void RemoveConditionPanels(string moduleCode)
|
||||
{
|
||||
foreach (string key in ConditionsPanelDic.Keys.ToList())
|
||||
{
|
||||
ModuleConditionsPanelEx panel;
|
||||
if (string.Equals(key, moduleCode, StringComparison.OrdinalIgnoreCase) ||
|
||||
!ConditionsPanelDic.TryGetValue(key, out panel) || panel == null || panel.IsDisposed)
|
||||
ConditionsPanelDic.Remove(key);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 记录当前U盾权限窗口
|
||||
/// </summary>
|
||||
@@ -44,4 +127,4 @@ namespace Lskj.Control.Model
|
||||
/// </summary>
|
||||
public static FrmProgressBar frmProgressBar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,215 @@ using DevExpress.XtraTab;
|
||||
using Lskj.Control.ZKFinger;
|
||||
using Lskj.Util;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Lskj.Model;
|
||||
using System.Reflection;
|
||||
using WinFormsControl = System.Windows.Forms.Control;
|
||||
|
||||
namespace Lskj.Control.Model
|
||||
{
|
||||
public static class StaticControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Releases static references owned by a closed legacy module. Cleanup is
|
||||
/// best-effort so it cannot change the module close result.
|
||||
/// </summary>
|
||||
public static void ReleaseModuleReferences(WinFormsControl moduleRoot, XtraTabPage modulePage, string moduleCode)
|
||||
{
|
||||
List<GridView> gridViews = new List<GridView>();
|
||||
try
|
||||
{
|
||||
gridViews = CollectGridViews(moduleRoot);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
TraceCleanupFailure("收集表格引用", exception);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (GridView gridView in gridViews)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveGridReferences(gridView);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
TraceCleanupFailure("释放表格拖拽引用", exception);
|
||||
}
|
||||
}
|
||||
|
||||
TryCleanup(() => RemoveConditionPanels(moduleCode), "释放条件面板引用");
|
||||
TryCleanup(() => RemoveProtectedReferences(moduleRoot, modulePage), "释放权限保护引用");
|
||||
TryCleanup(() => ClearRightMenuReferences(moduleRoot, gridViews), "释放右键菜单引用");
|
||||
TryCleanup(
|
||||
() => StaticBandedControl.ReleaseModuleReferences(moduleRoot, modulePage, moduleCode),
|
||||
"释放带状表格引用");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// DynamicModel caches retain completed tasks, result tables and
|
||||
// their closures. Always release them after other references.
|
||||
TryCleanup(() => ClearDataCaches(moduleRoot), "释放动态数据缓存");
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryCleanup(Action cleanup, string operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
TraceCleanupFailure(operation, exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TraceCleanupFailure(string operation, Exception exception)
|
||||
{
|
||||
Debug.WriteLine("释放旧模块引用失败[" + operation + "]:" + exception);
|
||||
}
|
||||
|
||||
private static List<GridView> CollectGridViews(WinFormsControl root)
|
||||
{
|
||||
List<GridView> result = new List<GridView>();
|
||||
if (root == null)
|
||||
return result;
|
||||
foreach (WinFormsControl control in EnumerateControls(root))
|
||||
{
|
||||
DevExpress.XtraGrid.GridControl grid = control as DevExpress.XtraGrid.GridControl;
|
||||
GridView view = grid == null ? null : grid.MainView as GridView;
|
||||
if (view != null && !result.Contains(view))
|
||||
result.Add(view);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<WinFormsControl> EnumerateControls(WinFormsControl root)
|
||||
{
|
||||
yield return root;
|
||||
foreach (WinFormsControl child in root.Controls)
|
||||
foreach (WinFormsControl nested in EnumerateControls(child))
|
||||
yield return nested;
|
||||
}
|
||||
|
||||
private static void RemoveGridReferences(GridView gridView)
|
||||
{
|
||||
GridDragGrid.DisposeRegistrations(GridViewDragGridDic, TargetViewDragGridDic, gridView);
|
||||
if (ReferenceEquals(SourceDragGridView, gridView) ||
|
||||
(SourceDragGridView != null && SourceDragGridView.GridControl != null && SourceDragGridView.GridControl.IsDisposed))
|
||||
SourceDragGridView = null;
|
||||
}
|
||||
|
||||
private static void RemoveConditionPanels(string moduleCode)
|
||||
{
|
||||
foreach (string key in ConditionsPanelDic.Keys.ToList())
|
||||
{
|
||||
ModuleConditionsPanelEx panel;
|
||||
if (string.Equals(key, moduleCode, StringComparison.OrdinalIgnoreCase) ||
|
||||
!ConditionsPanelDic.TryGetValue(key, out panel) || panel == null || panel.IsDisposed)
|
||||
ConditionsPanelDic.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveProtectedReferences(WinFormsControl root, XtraTabPage page)
|
||||
{
|
||||
while (page != null && DogVerifyModuleForms.Remove(page))
|
||||
{
|
||||
}
|
||||
foreach (XtraTabPage item in DogVerifyModuleForms.ToList())
|
||||
if (item == null || item.IsDisposed || IsContained(root, item))
|
||||
DogVerifyModuleForms.Remove(item);
|
||||
foreach (IForm item in DogVerifyNoPageForms.ToList())
|
||||
if (item == null || item.SubForm == null || item.SubForm.IsDisposed || IsContained(root, item.SubForm))
|
||||
DogVerifyNoPageForms.Remove(item);
|
||||
}
|
||||
|
||||
private static bool IsContained(WinFormsControl root, WinFormsControl value)
|
||||
{
|
||||
if (root == null || value == null)
|
||||
return false;
|
||||
if (ReferenceEquals(root, value))
|
||||
return true;
|
||||
foreach (WinFormsControl child in root.Controls)
|
||||
if (IsContained(child, value))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ClearRightMenuReferences(WinFormsControl root, List<GridView> gridViews)
|
||||
{
|
||||
if (_RightMenuGridView != null && (gridViews.Contains(_RightMenuGridView) ||
|
||||
(_RightMenuGridView.GridControl != null && _RightMenuGridView.GridControl.IsDisposed)))
|
||||
RightMenuGridView = null;
|
||||
if (RightMenuMyControl != null && RightMenuMyControl.MainGridEx != null &&
|
||||
(RightMenuMyControl.MainGridEx.IsDisposed || IsContained(root, RightMenuMyControl.MainGridEx)))
|
||||
RightMenuMyControl = null;
|
||||
if (BomUnionPage != null && (BomUnionPage.IsDisposed || IsContained(root, BomUnionPage)))
|
||||
BomUnionPage = null;
|
||||
if (AddParentGrid.Value != null && (AddParentGrid.Value.IsDisposed || IsContained(root, AddParentGrid.Value)))
|
||||
AddParentGrid = new KeyValuePair<string, GridControlEx>();
|
||||
}
|
||||
|
||||
private static void ClearDataCaches(WinFormsControl root)
|
||||
{
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
// Clear the root first because child enumeration can fail while a
|
||||
// DevExpress control is disposing its child collection.
|
||||
ClearDynamicModels(root);
|
||||
try
|
||||
{
|
||||
foreach (WinFormsControl control in EnumerateControls(root).Skip(1).ToList())
|
||||
ClearDynamicModels(control);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
TraceCleanupFailure("遍历动态数据缓存", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClearDynamicModels(object instance)
|
||||
{
|
||||
if (instance == null)
|
||||
return;
|
||||
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
for (Type type = instance.GetType(); type != null; type = type.BaseType)
|
||||
foreach (FieldInfo field in type.GetFields(flags | BindingFlags.DeclaredOnly))
|
||||
try
|
||||
{
|
||||
ClearDynamicModel(field.GetValue(instance));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.WriteLine("清理动态缓存字段失败:" + exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClearDynamicModel(object value)
|
||||
{
|
||||
DynamicModel model = value as DynamicModel;
|
||||
if (model == null || model.DataCaches == null)
|
||||
return;
|
||||
Dictionary<object, Hashtable> caches = model.DataCaches;
|
||||
foreach (Hashtable cache in caches.Values.OfType<Hashtable>().ToList())
|
||||
{
|
||||
foreach (IDisposable item in cache.Values.OfType<IDisposable>().ToList())
|
||||
try { item.Dispose(); } catch { }
|
||||
cache.Clear();
|
||||
}
|
||||
caches.Clear();
|
||||
model.DataCaches = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// 记录当前U盾权限窗口
|
||||
/// </summary>
|
||||
@@ -84,4 +282,4 @@ namespace Lskj.Control.Model
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
+154
-20
@@ -63,6 +63,7 @@ namespace Lskj.Control
|
||||
/// </summary>
|
||||
private MyControl _leftGridSearchObj;
|
||||
private GridDragTree _gridDragTree;
|
||||
private bool mModuleResourcesReleased;
|
||||
private GridDragGrid _gridDragGrid;
|
||||
private BandedGridDragGrid _bandedGridDragGrid;
|
||||
|
||||
@@ -156,6 +157,150 @@ namespace Lskj.Control
|
||||
this.Disposed += OnModuleExDisposed;
|
||||
}
|
||||
|
||||
public void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mModuleResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mModuleResourcesReleased = true;
|
||||
HashSet<ModuleGridDetailEx> details =
|
||||
new HashSet<ModuleGridDetailEx>();
|
||||
HashSet<ModuleGridEx> grids = new HashSet<ModuleGridEx>();
|
||||
foreach (System.Windows.Forms.Control control in
|
||||
EnumerateModuleControls(this))
|
||||
{
|
||||
ModuleGridDetailEx detail = control as ModuleGridDetailEx;
|
||||
if (detail != null)
|
||||
{
|
||||
details.Add(detail);
|
||||
}
|
||||
ModuleGridEx grid = control as ModuleGridEx;
|
||||
if (grid != null)
|
||||
{
|
||||
grids.Add(grid);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ModuleGridDetailEx detail in details)
|
||||
{
|
||||
detail.ReleaseResourcesForDispose();
|
||||
}
|
||||
foreach (ModuleGridEx grid in grids)
|
||||
{
|
||||
grid.SaveEvent -= SetDetailGridView;
|
||||
grid.OnExportCallBack -= SetExportGridView;
|
||||
grid.ReleaseResourcesForDispose();
|
||||
}
|
||||
|
||||
MyControl leftSearch = _leftGridSearchObj;
|
||||
_leftGridSearchObj = null;
|
||||
if (leftSearch != null)
|
||||
{
|
||||
leftSearch.OnDataSourceBindCallBack -= OnLeftControlObjDataSourceBindCallBack;
|
||||
leftSearch.Dispose();
|
||||
}
|
||||
|
||||
GridDragTree dragTree = _gridDragTree;
|
||||
_gridDragTree = null;
|
||||
if (dragTree != null)
|
||||
{
|
||||
dragTree.OnDragComplete -= OnDragTreeCompleted;
|
||||
dragTree.Dispose();
|
||||
}
|
||||
|
||||
GridDragGrid dragGrid = _gridDragGrid;
|
||||
_gridDragGrid = null;
|
||||
if (dragGrid != null)
|
||||
{
|
||||
dragGrid.OnDragComplete -= OnDragGridCompleted;
|
||||
dragGrid.Dispose();
|
||||
}
|
||||
|
||||
BandedGridDragGrid bandedDragGrid = _bandedGridDragGrid;
|
||||
_bandedGridDragGrid = null;
|
||||
if (bandedDragGrid != null)
|
||||
{
|
||||
bandedDragGrid.OnDragComplete -= OnDragBandedGridCompleted;
|
||||
bandedDragGrid.Dispose();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (treeLeft != null)
|
||||
{
|
||||
treeLeft.TreeNodeSelectAfter -= OnTreeLeftTreeNodeSelected;
|
||||
treeLeft.OnTreeNodeMouseDoubleClick -= TreeLeft_OnTreeNodeMouseDoubleClick;
|
||||
}
|
||||
if (gridLeft != null && gridLeft.GridView != null)
|
||||
{
|
||||
gridLeft.GridView.RowClick -= OnGridViewRowClick;
|
||||
}
|
||||
if (treeGridLeft != null && treeGridLeft.TreeListObj != null)
|
||||
{
|
||||
treeGridLeft.TreeListObj.Click -= TreeListObj_Click;
|
||||
treeGridLeft.TreeListObj.BeforeExpand -= TreeListObj_BeforeExpand;
|
||||
treeGridLeft.TreeListObj.BeforeCollapse -= TreeListObj_BeforeCollapse;
|
||||
}
|
||||
if (MainBodyTab != null)
|
||||
{
|
||||
MainBodyTab.SelectedPageChanged -= MainBodyTab_SelectedPageChanged;
|
||||
}
|
||||
if (excelControlEx1 != null)
|
||||
{
|
||||
excelControlEx1.SaveCallBack -= OnExcelSaveClick;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A partially disposed child control must not stop cleanup.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt module disposal.
|
||||
}
|
||||
|
||||
OnLeftGridViewRowClickCallBack = null;
|
||||
OnLeftTreeViewRowClickCallBack = null;
|
||||
if (Details != null)
|
||||
{
|
||||
Details.Clear();
|
||||
}
|
||||
LeftRowObj = null;
|
||||
ColumnNameTable = null;
|
||||
_currentRow = null;
|
||||
ExcelControlObj = null;
|
||||
Model = null;
|
||||
SysModel = null;
|
||||
}
|
||||
|
||||
private static IEnumerable<System.Windows.Forms.Control>
|
||||
EnumerateModuleControls(System.Windows.Forms.Control parent)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
foreach (System.Windows.Forms.Control child in parent.Controls)
|
||||
{
|
||||
yield return child;
|
||||
foreach (System.Windows.Forms.Control nested in
|
||||
EnumerateModuleControls(child))
|
||||
{
|
||||
yield return nested;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Excel 控件包含 SpreadsheetControl、BarManager 和命令注册项,
|
||||
/// 普通表格模块不应在设计器初始化阶段创建这些重型资源。
|
||||
@@ -253,7 +398,11 @@ namespace Lskj.Control
|
||||
if (Model.HasOperPrivilege() && model.IsBaseModule)
|
||||
{
|
||||
// 有权限则允许拖拽
|
||||
_gridDragTree?.Dispose();
|
||||
if (_gridDragTree != null)
|
||||
{
|
||||
_gridDragTree.OnDragComplete -= OnDragTreeCompleted;
|
||||
_gridDragTree.Dispose();
|
||||
}
|
||||
_gridDragTree = new GridDragTree(this.ModuleGridObj.GridControlObj.GridView, this.treeLeft.TreeView);
|
||||
_gridDragTree.CanDragParentNode = true;
|
||||
_gridDragTree.OnDragComplete += new GridDragTreeCompleteEventHandler(OnDragTreeCompleted);
|
||||
@@ -484,7 +633,6 @@ namespace Lskj.Control
|
||||
{
|
||||
case 1:
|
||||
case 4://左侧为树节点
|
||||
this.ModuleGridObj.LeftTreeViewEx = this.treeLeft;
|
||||
Task<DataRow> baseLeftTreeFieldTask = cachesDic.AddTask(this, "BaseLeftTreeField", new Task<DataRow>(() =>
|
||||
{
|
||||
return BaseModuleImpl.GetBaseLeftTreeField(dynamicModel.ModuleCode);//获取表格左侧树字段
|
||||
@@ -538,12 +686,7 @@ namespace Lskj.Control
|
||||
DataTable customQueryFieldsTab = customQueryFieldsTask.Result;
|
||||
if (customQueryFieldsTab != null && customQueryFieldsTab.Rows.Count > 0)
|
||||
{
|
||||
Task<MyControl> leftGridSearchObjTask = cachesDic.AddTask(this, "LeftGridSearchObj", new Task<MyControl>(() =>
|
||||
{
|
||||
string searchSql = baseLeftTreeFieldTask.Result["fieldsql"] + "";
|
||||
return new MyControl(searchSql, sysModel.IsTreeTable ? this.treeGridLeft as GridControlEx : this.gridLeft);
|
||||
}));
|
||||
ModuleGridDetailObj._leftGridSearchObj = leftGridSearchObjTask.Result;
|
||||
// MyControl 必须由后续 UI 初始化阶段创建。
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -565,7 +708,7 @@ namespace Lskj.Control
|
||||
Task<DataTable> customColumnByDatabaseTask = cachesDic.AddTask(gridLeft, "CustomColumnByDatabase", new Task<DataTable>(() =>
|
||||
{
|
||||
string customColumKey = GridCustomColumnStruct.BaseLeftGridView + dynamicModel.ModuleCode;
|
||||
return gridLeft.GridView.GetCustomColumnByDatabase(customColumKey);
|
||||
return GridExtend.GetCustomColumnByDatabase(customColumKey);
|
||||
}));
|
||||
}
|
||||
else
|
||||
@@ -573,12 +716,11 @@ namespace Lskj.Control
|
||||
Task<DataTable> customColumnByDatabaseTask = cachesDic.AddTask(treeGridLeft, "CustomColumnByDatabase", new Task<DataTable>(() =>
|
||||
{
|
||||
string customColumKey = GridCustomColumnStruct.BaseLeftGridView + dynamicModel.ModuleCode;
|
||||
return treeGridLeft.GridView.GetCustomColumnByDatabase(customColumKey);
|
||||
return GridExtend.GetCustomColumnByDatabase(customColumKey);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleGridObj.LeftGridEx = sysModel.IsTreeTable ? this.treeGridLeft : this.gridLeft;
|
||||
break;
|
||||
}
|
||||
if (dynamicModel is DynamicExcelModel)//isExcel
|
||||
@@ -2012,15 +2154,7 @@ namespace Lskj.Control
|
||||
private void OnModuleExDisposed(object sender, EventArgs e)
|
||||
{
|
||||
this.Disposed -= OnModuleExDisposed;
|
||||
|
||||
_gridDragTree?.Dispose();
|
||||
_gridDragTree = null;
|
||||
|
||||
_gridDragGrid?.Dispose();
|
||||
_gridDragGrid = null;
|
||||
|
||||
_bandedGridDragGrid?.Dispose();
|
||||
_bandedGridDragGrid = null;
|
||||
ReleaseResourcesForDispose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace Lskj.Control
|
||||
/// </summary>
|
||||
public partial class ModuleGridDetailEx : UserControl
|
||||
{
|
||||
private bool mModuleResourcesReleased;
|
||||
private bool mDetailPageCachesPrepared;
|
||||
|
||||
/// <summary>
|
||||
/// 系统模块实体对象
|
||||
@@ -147,6 +149,68 @@ namespace Lskj.Control
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
internal void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mModuleResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mModuleResourcesReleased = true;
|
||||
MyControl searchObj = SearchObj;
|
||||
if (searchObj != null)
|
||||
{
|
||||
searchObj.OnSearchAfterCallBack -= SearchObj_ClearDetails_DoubleMode;
|
||||
searchObj.OnLastQueryTriggered -= SearchObj_ClearDetails_DoubleMode;
|
||||
searchObj.OnSearchAfterCallBack -= SearchObj_ClearDetails;
|
||||
searchObj.OnLastQueryTriggered -= SearchObj_ClearDetails;
|
||||
}
|
||||
|
||||
if (ModuleGridObj != null)
|
||||
{
|
||||
ModuleGridObj.AfterRefreshingCallBack -= ModuleGridObj_AfterRefreshingCallBack;
|
||||
try
|
||||
{
|
||||
GridControlEx grid = ModuleGridObj.GridControlObj;
|
||||
if (grid != null && grid.GridView != null)
|
||||
{
|
||||
grid.GridView.DoubleClick -= GridView_DoubleClick;
|
||||
grid.GridView.DoubleClick -= OnGridViewDoubleClick;
|
||||
grid.GridView.Click -= OnGridViewDoubleClick;
|
||||
grid.GridView.MouseDown -= GridView_MouseDown;
|
||||
grid.GridView.FocusedRowObjectChanged -= OnGridViewFocusedRowObjectChanged;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A partially disposed DevExpress view must not stop cleanup.
|
||||
}
|
||||
ModuleGridObj.ReleaseResourcesForDispose();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt control disposal.
|
||||
}
|
||||
|
||||
OnGridViewRowClickCallBack = null;
|
||||
if (GridDetailList != null)
|
||||
{
|
||||
GridDetailList.Clear();
|
||||
}
|
||||
datamodel.Clear();
|
||||
_leftGridSearchObj = null;
|
||||
Model = null;
|
||||
SysModel = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>说明:初始化控件</para>
|
||||
/// <para>创建人:龚宇超</para>
|
||||
@@ -189,6 +253,7 @@ namespace Lskj.Control
|
||||
}
|
||||
else
|
||||
{
|
||||
PrepareDetailPageCaches(dataCaches);
|
||||
// 初始化底部多标签
|
||||
this.InitializePages();
|
||||
}
|
||||
@@ -220,7 +285,6 @@ namespace Lskj.Control
|
||||
//获取通用数据
|
||||
Task<ModuleModel> sysModelTask = cachesDic.GetTask<ModuleModel>(this, "SysModel");
|
||||
Task<DynamicModel> dynamicModelTask = cachesDic.GetTask<DynamicModel>(this, "DynamicModel");
|
||||
Task<List<GridDetailModel>> detailsTask = cachesDic.GetTask<List<GridDetailModel>>(this, "Details");
|
||||
ModuleGridObj._leftGridSearchObj = _leftGridSearchObj;
|
||||
Task<bool> getDataCachesTask = cachesDic.AddTask(this, "DataCaches", new Task<bool>(() =>
|
||||
{
|
||||
@@ -237,23 +301,29 @@ namespace Lskj.Control
|
||||
{
|
||||
cachesDic.AddTask(tcButtom, "ParentPrimaryKey", parentPrimaryKeyTask);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(sysModel.MainModuleCodeField) && this.ModuleGridObj.GridControlObj.GridView.Columns.ColumnByFieldName(sysModel.MainModuleCodeField) != null)
|
||||
{
|
||||
//InitializeDynamicPages();
|
||||
}
|
||||
else
|
||||
{
|
||||
//添加数据到mControl
|
||||
cachesDic.AddTask(tcButtom, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(tcButtom, "Details", detailsTask);
|
||||
// 初始化底部多标签
|
||||
this.tcButtom.GetDataCaches(cachesDic);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
private void PrepareDetailPageCaches(
|
||||
Dictionary<object, Hashtable> cachesDic)
|
||||
{
|
||||
if (mDetailPageCachesPrepared || cachesDic == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDetailPageCachesPrepared = true;
|
||||
Task<DynamicModel> dynamicModelTask =
|
||||
cachesDic.GetTask<DynamicModel>(this, "DynamicModel");
|
||||
Task<List<GridDetailModel>> detailsTask =
|
||||
cachesDic.GetTask<List<GridDetailModel>>(this, "Details");
|
||||
cachesDic.AddTask(tcButtom, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(tcButtom, "Details", detailsTask);
|
||||
this.tcButtom.GetDataCaches(cachesDic);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>说明:初始化底部多标签数据</para>
|
||||
|
||||
+1
@@ -15,6 +15,7 @@
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
ReleaseResourcesForDispose();
|
||||
Lskj.Control.Model.PrintUtil.OnAfterPrint -=
|
||||
new System.EventHandler(OnReportPrintAfter);
|
||||
if (components != null)
|
||||
|
||||
@@ -428,6 +428,7 @@ namespace Lskj.Control
|
||||
/// 自定义查询条件
|
||||
/// </summary>
|
||||
public MyControl SearchObj { get; private set; }
|
||||
private bool mModuleResourcesReleased;
|
||||
/// <summary>
|
||||
/// 左查询条件
|
||||
/// </summary>
|
||||
@@ -520,6 +521,24 @@ namespace Lskj.Control
|
||||
searchObj = new MyControl(ReplaceBmpField(this.SysModel.MenuSql), gcMain, LeftTreeViewEx, LeftGridEx, _leftGridSearchObj);//替换sql语句中的bmp字段
|
||||
searchObj.SpecialLeftTable = this.SpecialLeftTable;
|
||||
searchObj.Model = Model;
|
||||
if (!fixedQuery && Model.DataCaches != null)
|
||||
{
|
||||
searchObj.OtherParams = Model.OtherParams();
|
||||
DynamicModel searchModel = Model;
|
||||
DataTable searchControls = _queryTable;
|
||||
Model.DataCaches.AddTask(searchObj, "DynamicModel",
|
||||
new Task<DynamicModel>(() => searchModel));
|
||||
Model.DataCaches.AddTask(searchObj, "ControlsTable",
|
||||
new Task<DataTable>(() => searchControls));
|
||||
searchObj.GetSearchDataCaches(Model.DataCaches);
|
||||
}
|
||||
}
|
||||
if (this.MrpClickMenus == null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.GetValue(
|
||||
this,
|
||||
"UnionBaseGridRightMenus",
|
||||
out this.MrpClickMenus);
|
||||
}
|
||||
this.SearchObj = searchObj;
|
||||
// 搜索区域复用当前模块配置,MyControl 内部会校验模块号,不一致时仍按原逻辑查询。
|
||||
@@ -2464,8 +2483,6 @@ namespace Lskj.Control
|
||||
|
||||
form.SubForm.Dispose();
|
||||
form = null;
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -3489,7 +3506,7 @@ namespace Lskj.Control
|
||||
{
|
||||
this.SearchObj.SearchLastGrid();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//GridColumnCollection gridColumns = this.gcMain.GridView.Columns;
|
||||
@@ -3695,23 +3712,111 @@ namespace Lskj.Control
|
||||
private void OnModuleGridExDisposed(object sender, EventArgs e)
|
||||
{
|
||||
this.Disposed -= OnModuleGridExDisposed;
|
||||
ReleaseResourcesForDispose();
|
||||
}
|
||||
|
||||
internal void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mModuleResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mModuleResourcesReleased = true;
|
||||
PrintUtil.OnAfterPrint -= OnReportPrintAfter;
|
||||
|
||||
if (SearchObj != null)
|
||||
MyControl searchObj = SearchObj;
|
||||
SearchObj = null;
|
||||
if (searchObj != null)
|
||||
{
|
||||
SearchObj.OnSearchBeforeCallBack -= OnSearchBeforeCallBack;
|
||||
SearchObj.OnSearchAfterCallBack -= OnSearchAfterCallBack;
|
||||
SearchObj.OnDataSourceBindCallBack -= OnMainSearchDataSourceBindCallBack;
|
||||
if (ReferenceEquals(StaticControl.RightMenuMyControl, SearchObj))
|
||||
searchObj.OnSearchBeforeCallBack -= OnSearchBeforeCallBack;
|
||||
searchObj.OnSearchAfterCallBack -= OnSearchAfterCallBack;
|
||||
searchObj.OnDataSourceBindCallBack -= OnMainSearchDataSourceBindCallBack;
|
||||
if (ReferenceEquals(StaticControl.RightMenuMyControl, searchObj))
|
||||
{
|
||||
StaticControl.RightMenuMyControl = null;
|
||||
}
|
||||
searchObj.Dispose();
|
||||
}
|
||||
|
||||
if (gcMain != null && ReferenceEquals(StaticControl.RightMenuGridView, gcMain.GridView))
|
||||
try
|
||||
{
|
||||
StaticControl.RightMenuGridView = null;
|
||||
if (gcMain != null)
|
||||
{
|
||||
if (ReferenceEquals(StaticControl.RightMenuGridView, gcMain.GridView))
|
||||
{
|
||||
StaticControl.RightMenuGridView = null;
|
||||
}
|
||||
if (gcMain.GridView != null)
|
||||
{
|
||||
gcMain.GridView.FocusedRowObjectChanged -= OnGridViewFocusedRowObjectChanged;
|
||||
gcMain.GridView.ShowingEditor -= OnGridViewShowingEditor;
|
||||
gcMain.GridView.DoubleClick -= OnGridViewDoubleClick;
|
||||
gcMain.GridView.MouseDown -= OnGridViewMouseDown;
|
||||
gcMain.GridView.MouseDown -= OnGridMouseDown;
|
||||
gcMain.GridView.MouseMove -= OnGridMouseMove;
|
||||
gcMain.GridView.MouseUp -= OnGridMouseUp;
|
||||
}
|
||||
if (gcMain.CustomGroupBandEx != null)
|
||||
{
|
||||
gcMain.CustomGroupBandEx.GridView.FocusedRowObjectChanged -= OnGridViewFocusedRowObjectChanged;
|
||||
gcMain.CustomGroupBandEx.GridView.ShowingEditor -= OnGridViewShowingEditor;
|
||||
}
|
||||
if (gcMain.ParentControl != null &&
|
||||
ReferenceEquals(gcMain.ParentControl, searchObj))
|
||||
{
|
||||
gcMain.ParentControl = null;
|
||||
}
|
||||
gcMain.Model = null;
|
||||
gcMain.SysModel = null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A partially disposed DevExpress view must not stop module cleanup.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Model != null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt control disposal.
|
||||
}
|
||||
|
||||
OnSaveGridCallBack = null;
|
||||
AfterDeleteGridCallBack = null;
|
||||
RightGridCallBack = null;
|
||||
DetailRightGridCallBack = null;
|
||||
OnCloseCallback = null;
|
||||
AfterRefreshingCallBack = null;
|
||||
SaveEvent = null;
|
||||
OnExportCallBack = null;
|
||||
verifyDetailsTab = null;
|
||||
|
||||
if (m_dragRowShadow != null)
|
||||
{
|
||||
m_dragRowShadow.Dispose();
|
||||
m_dragRowShadow = null;
|
||||
}
|
||||
ButtonModeRightMenus.Clear();
|
||||
RightButtons.Clear();
|
||||
itemCommonList.Clear();
|
||||
LineStatus.Clear();
|
||||
_leftGridSearchObj = null;
|
||||
LeftTreeViewEx = null;
|
||||
LeftGridEx = null;
|
||||
SpecialLeftTable = null;
|
||||
ParentGridEx = null;
|
||||
ParentControlEx = null;
|
||||
ParentControlObj = null;
|
||||
TabObj = null;
|
||||
Model = null;
|
||||
SysModel = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3993,32 +4098,6 @@ namespace Lskj.Control
|
||||
{
|
||||
return BaseModuleImpl.GetSchemesList(dynamicModel.ModuleId);//获取高级查询条件模版
|
||||
}));
|
||||
Task<DataTable> mrpClickMenusTask = cachesDic.GetTask<DataTable>(this, "UnionBaseGridRightMenus");
|
||||
//InitializeQueryCondition
|
||||
Task<MyControl> searchObjTask = cachesDic.AddTask(this, "SearchObj", new Task<MyControl>(() =>
|
||||
{
|
||||
DataTable queryTable = customQueryFieldsTask.Result;
|
||||
bool fixedQuery = queryTable == null || queryTable.Rows.Count == 0;
|
||||
if (MrpClickMenus == null && mrpClickMenusTask != null)
|
||||
{
|
||||
MrpClickMenus = mrpClickMenusTask.Result;
|
||||
}
|
||||
MyControl myControl = new MyControl(sysModel.MenuSql, gcMain, LeftTreeViewEx, LeftGridEx, _leftGridSearchObj)
|
||||
{
|
||||
SpecialLeftTable = this.SpecialLeftTable,
|
||||
Model = dynamicModel,
|
||||
SystemModel = sysModel,
|
||||
MrpClickMenus = this.MrpClickMenus
|
||||
};
|
||||
if (!fixedQuery)
|
||||
{
|
||||
myControl.OtherParams = dynamicModel.OtherParams();
|
||||
cachesDic.AddTask(myControl, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(myControl, "ControlsTable", customQueryFieldsTask);
|
||||
myControl.GetSearchDataCaches(cachesDic);
|
||||
}
|
||||
return myControl;
|
||||
}));
|
||||
// 搜索区域与当前模块共享同一个模块配置任务,避免再次查询模块信息。
|
||||
cachesDic.AddTask(pl_top_search, "SysModel", sysModelTask);
|
||||
//Task<DataTable> searchBaseGridRightMenusTask = cachesDic.AddTask(pl_top_search, "BaseGridRightMenus", new Task<DataTable>(() =>
|
||||
|
||||
+7
-2
@@ -14,9 +14,14 @@ namespace Lskj.Control
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
Lskj.Control.Model.PrintUtil.OnAfterPrint -=
|
||||
new EventHandler(OnReportPrintAfter);
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace Lskj.Control
|
||||
/// </summary>
|
||||
public partial class ReplacementDetailEx : UserControl
|
||||
{
|
||||
private bool mResourcesReleased;
|
||||
private bool mDetailPageCachesPrepared;
|
||||
/// <summary>
|
||||
/// 系统模块实体对象
|
||||
/// </summary>
|
||||
@@ -102,6 +104,39 @@ namespace Lskj.Control
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
internal void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
if (ModuleGridObj != null)
|
||||
{
|
||||
ModuleGridObj.ReleaseResourcesForDispose();
|
||||
}
|
||||
try
|
||||
{
|
||||
if (Model != null && Model.DataCaches != null)
|
||||
{
|
||||
Model.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Cache cleanup must not interrupt control disposal.
|
||||
}
|
||||
|
||||
if (GridDetailList != null)
|
||||
{
|
||||
GridDetailList.Clear();
|
||||
}
|
||||
_leftGridSearchObj = null;
|
||||
Model = null;
|
||||
SysModel = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>说明:初始化控件</para>
|
||||
/// <para>创建人:龚宇超</para>
|
||||
@@ -128,6 +163,7 @@ namespace Lskj.Control
|
||||
this.ModuleGridObj.InitializeControl(sysModel, dyncModel);
|
||||
RefreshDetail = this.SysModel.RefreshDetail == "0";
|
||||
Console.WriteLine(DateTime.Now);
|
||||
PrepareDetailPageCaches(dyncModel.DataCaches);
|
||||
// 初始化底部多标签
|
||||
this.InitializePages();
|
||||
Console.WriteLine(DateTime.Now);
|
||||
@@ -162,15 +198,27 @@ namespace Lskj.Control
|
||||
//获取通用数据
|
||||
Task<ModuleModel> sysModelTask = cachesDic.GetTask<ModuleModel>(this, "SysModel");
|
||||
Task<DynamicModel> dynamicModelTask = cachesDic.GetTask<DynamicModel>(this, "DynamicModel");
|
||||
Task<List<GridDetailModel>> detailsTask = cachesDic.GetTask<List<GridDetailModel>>(this, "Details");
|
||||
cachesDic.AddTask(ModuleGridObj, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(ModuleGridObj, "SysModel", sysModelTask);
|
||||
cachesDic.AddTask(ModuleGridObj, "Details", detailsTask);
|
||||
cachesDic.AddTask(tcButtom, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(tcButtom, "Details", detailsTask);
|
||||
//初始化顶部表格
|
||||
ModuleGridObj.GetDataCaches(cachesDic);
|
||||
// 初始化底部多标签
|
||||
}
|
||||
|
||||
private void PrepareDetailPageCaches(
|
||||
Dictionary<object, Hashtable> cachesDic)
|
||||
{
|
||||
if (mDetailPageCachesPrepared || cachesDic == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDetailPageCachesPrepared = true;
|
||||
Task<DynamicModel> dynamicModelTask =
|
||||
cachesDic.GetTask<DynamicModel>(this, "DynamicModel");
|
||||
Task<List<GridDetailModel>> detailsTask =
|
||||
cachesDic.GetTask<List<GridDetailModel>>(this, "Details");
|
||||
cachesDic.AddTask(tcButtom, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(tcButtom, "Details", detailsTask);
|
||||
tcButtom.GetDataCaches(cachesDic);
|
||||
}
|
||||
|
||||
@@ -650,4 +698,4 @@ namespace Lskj.Control
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2112,6 +2112,7 @@ namespace Lskj.Control
|
||||
public override int SetGridViewDataSource(DbDataAdapter adapter, bool selectRowHandler = true)
|
||||
{
|
||||
if (adapter == null) return 0;
|
||||
DbDataAdapter previousAdapter = this.AdapterObj;
|
||||
if (this.ColumnList == null || this.ColumnList.Count == 0)
|
||||
{
|
||||
this.gcMain.Bands.Clear();
|
||||
@@ -2122,53 +2123,74 @@ namespace Lskj.Control
|
||||
lastNodeIndex = 0;
|
||||
if (selectRowHandler) lastNodeIndex = this.TreeListObj.GetVisibleIndexByNode(this.TreeListObj.FocusedNode);
|
||||
|
||||
this.AdapterObj = adapter;
|
||||
DataSet dataSet = new DataSet();
|
||||
//adapter.Fill(dataSet, "SetGridViewDataSource");
|
||||
// 重连配置
|
||||
int maxRetryCount = 2; // 次数
|
||||
int retryDelay = 1000; // 等待时间
|
||||
for (int i = 0; i < maxRetryCount; i++)
|
||||
try
|
||||
{
|
||||
try
|
||||
for (int i = 0; i < maxRetryCount; i++)
|
||||
{
|
||||
adapter.Fill(dataSet, "SetGridViewDataSource");
|
||||
break;//连接成功
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
// 判断是否是连接相关错误
|
||||
if (IsConnectionError(ex.Number) ||
|
||||
ex.Message.Contains("物理连接不可用") ||
|
||||
ex.Message.Contains("传输级错误"))
|
||||
try
|
||||
{
|
||||
if (i < maxRetryCount - 1)
|
||||
adapter.Fill(dataSet, "SetGridViewDataSource");
|
||||
break;//连接成功
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
// 判断是否是连接相关错误
|
||||
if (IsConnectionError(ex.Number) ||
|
||||
ex.Message.Contains("物理连接不可用") ||
|
||||
ex.Message.Contains("传输级错误"))
|
||||
{
|
||||
SqlConnection.ClearAllPools();
|
||||
System.Threading.Thread.Sleep(retryDelay);
|
||||
continue; // 重试
|
||||
if (i < maxRetryCount - 1)
|
||||
{
|
||||
SqlConnection.ClearAllPools();
|
||||
System.Threading.Thread.Sleep(retryDelay);
|
||||
continue; // 重试
|
||||
}
|
||||
else
|
||||
{
|
||||
// 最后一次重试失败,抛出错误
|
||||
throw new Exception($"经过 {maxRetryCount} 次重试后仍无法连接到数据库: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 最后一次重试失败,抛出错误
|
||||
throw new Exception($"经过 {maxRetryCount} 次重试后仍无法连接到数据库: {ex.Message}", ex);
|
||||
// 其他SQL错误直接抛出
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其他SQL错误直接抛出
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
dataSet.Dispose();
|
||||
DisposeDataAdapter(adapter);
|
||||
throw;
|
||||
}
|
||||
|
||||
DataTable resultTable = dataSet.Tables.Count > 0 ? dataSet.Tables[0] : null;
|
||||
int rowCount = resultTable == null ? 0 : resultTable.Rows.Count;
|
||||
if (resultTable != null)
|
||||
{
|
||||
dataSet.Tables.Remove(resultTable);
|
||||
}
|
||||
dataSet.Dispose();
|
||||
|
||||
DbCommandBuilder cb = SqlHelper.dbFactory.CreateCommandBuilder();
|
||||
cb.DataAdapter = this.AdapterObj;
|
||||
DisposeAdapterCommandBuilder();
|
||||
if (previousAdapter != null && !ReferenceEquals(previousAdapter, adapter))
|
||||
{
|
||||
DisposeDataAdapter(previousAdapter);
|
||||
}
|
||||
this.AdapterObj = adapter;
|
||||
|
||||
SetAdapterCommandBuilder(this.AdapterObj);
|
||||
//SqlCommandBuilder cb = new SqlCommandBuilder(this.AdapterObj);
|
||||
|
||||
GetTreeExpanded();
|
||||
this.gcMain.DataSource = dataSet.Tables[0];
|
||||
this.gcMain.DataSource = resultTable;
|
||||
this.SetAutoColumns();
|
||||
//根据记录展开对应节点
|
||||
foreach (TreeListNode treeListNode in treeListNodes)
|
||||
@@ -2193,7 +2215,7 @@ namespace Lskj.Control
|
||||
{
|
||||
this.TreeListObj.FocusedNode = lastNode;
|
||||
}
|
||||
return dataSet.Tables[0] != null ? dataSet.Tables[0].Rows.Count : 0;
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2540,60 +2540,83 @@ namespace Lskj.Control
|
||||
public override int SetGridViewDataSource(DbDataAdapter adapter, bool selectRowHandler = true)
|
||||
{
|
||||
if (adapter == null) return 0;
|
||||
DbDataAdapter previousAdapter = this.AdapterObj;
|
||||
if (this.ColumnList == null || this.ColumnList.Count == 0)
|
||||
{
|
||||
this.TreeListObj.Columns.Clear();
|
||||
}
|
||||
lastNodeIndex = 0;
|
||||
if (selectRowHandler) lastNodeIndex = this.TreeListObj.GetVisibleIndexByNode(this.TreeListObj.FocusedNode);
|
||||
this.AdapterObj = adapter;
|
||||
DataSet dataSet = new DataSet();
|
||||
//adapter.Fill(dataSet, "SetGridViewDataSource");
|
||||
|
||||
// 重连配置
|
||||
int maxRetryCount = 2; // 次数
|
||||
int retryDelay = 1000; // 等待时间
|
||||
for (int i = 0; i < maxRetryCount; i++)
|
||||
try
|
||||
{
|
||||
try
|
||||
for (int i = 0; i < maxRetryCount; i++)
|
||||
{
|
||||
adapter.Fill(dataSet, "SetGridViewDataSource");
|
||||
break;//连接成功
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
// 判断是否是连接相关错误
|
||||
if (IsConnectionError(ex.Number) ||
|
||||
ex.Message.Contains("物理连接不可用") ||
|
||||
ex.Message.Contains("传输级错误"))
|
||||
try
|
||||
{
|
||||
if (i < maxRetryCount - 1)
|
||||
adapter.Fill(dataSet, "SetGridViewDataSource");
|
||||
break;//连接成功
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
// 判断是否是连接相关错误
|
||||
if (IsConnectionError(ex.Number) ||
|
||||
ex.Message.Contains("物理连接不可用") ||
|
||||
ex.Message.Contains("传输级错误"))
|
||||
{
|
||||
SqlConnection.ClearAllPools();
|
||||
System.Threading.Thread.Sleep(retryDelay);
|
||||
continue; // 重试
|
||||
if (i < maxRetryCount - 1)
|
||||
{
|
||||
SqlConnection.ClearAllPools();
|
||||
System.Threading.Thread.Sleep(retryDelay);
|
||||
continue; // 重试
|
||||
}
|
||||
else
|
||||
{
|
||||
// 最后一次重试失败,抛出错误
|
||||
throw new Exception($"经过 {maxRetryCount} 次重试后仍无法连接到数据库: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 最后一次重试失败,抛出错误
|
||||
throw new Exception($"经过 {maxRetryCount} 次重试后仍无法连接到数据库: {ex.Message}", ex);
|
||||
// 其他SQL错误直接抛出
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 其他SQL错误直接抛出
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
DbCommandBuilder cb = SqlHelper.dbFactory.CreateCommandBuilder();
|
||||
cb.DataAdapter = this.AdapterObj;
|
||||
catch
|
||||
{
|
||||
dataSet.Dispose();
|
||||
DisposeDataAdapter(adapter);
|
||||
throw;
|
||||
}
|
||||
DataTable resultTable = dataSet.Tables.Count > 0 ? dataSet.Tables[0] : null;
|
||||
int rowCount = resultTable == null ? 0 : resultTable.Rows.Count;
|
||||
if (resultTable != null)
|
||||
{
|
||||
dataSet.Tables.Remove(resultTable);
|
||||
}
|
||||
dataSet.Dispose();
|
||||
|
||||
DisposeAdapterCommandBuilder();
|
||||
if (previousAdapter != null && !ReferenceEquals(previousAdapter, adapter))
|
||||
{
|
||||
DisposeDataAdapter(previousAdapter);
|
||||
}
|
||||
this.AdapterObj = adapter;
|
||||
|
||||
SetAdapterCommandBuilder(this.AdapterObj);
|
||||
//SqlCommandBuilder cb = new SqlCommandBuilder(this.AdapterObj);
|
||||
|
||||
|
||||
GetTreeExpanded();
|
||||
|
||||
this.TreeListObj.DataSource = dataSet.Tables[0];
|
||||
this.TreeListObj.DataSource = resultTable;
|
||||
this.AdjustIndicatorWidthSmart();
|
||||
this.SetAutoColumns();
|
||||
|
||||
@@ -2609,7 +2632,7 @@ namespace Lskj.Control
|
||||
{
|
||||
this.TreeListObj.CollapseAll();
|
||||
}
|
||||
return dataSet.Tables[0] != null ? dataSet.Tables[0].Rows.Count : 0;
|
||||
return rowCount;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +185,18 @@ namespace Lskj.Main
|
||||
{
|
||||
if (_cefInitialized)
|
||||
{
|
||||
CefRuntime.Shutdown();
|
||||
bool browsersClosed =
|
||||
CefBrowserRuntimeLifetime.CloseAllBrowsersAndWait(5000);
|
||||
if (browsersClosed)
|
||||
{
|
||||
CefRuntime.Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Instance.WriteLog(
|
||||
"[CEF_LIFECYCLE] CefRuntime.Shutdown skipped " +
|
||||
"because browser close callbacks are incomplete.");
|
||||
}
|
||||
_cefInitialized = false;
|
||||
}
|
||||
_mainProcessInitialized = false;
|
||||
@@ -234,14 +245,18 @@ namespace Lskj.Main
|
||||
commandLine.AppendSwitch("ignore-certificate-errors", "1");
|
||||
commandLine.AppendSwitch("allow-running-insecure-content", "1");
|
||||
|
||||
//如果注册表中CefMultithreading不为1,并且根目录中不存在BrowserMultithreading.txt"文件,就是单线程模式
|
||||
//只要有一个条件满足就是多线程模式
|
||||
if (!BrowserMultithreading() && !File.Exists(PubUtil.AbsolutelyPath + "BrowserMultithreading.txt"))
|
||||
{
|
||||
commandLine.AppendSwitch("single-process", "1");//单线程模式,默认开启。(开启单线程模式后会影响浏览器的性能)
|
||||
}
|
||||
// CEF's single-process switch is unsupported and is unrelated
|
||||
// to MultiThreadedMessageLoop. Keep renderer and utility work
|
||||
// in CEF's normal child processes, as in the official sample.
|
||||
|
||||
commandLine.AppendSwitch("no-proxy-server");
|
||||
// CEF 87 can terminate the host with STATUS_WX86_BREAKPOINT
|
||||
// while creating the first browser on machines whose GPU
|
||||
// driver does not support the legacy compositor path. Keep
|
||||
// software rendering enabled, but bypass GPU initialization.
|
||||
commandLine.AppendSwitch("disable-gpu");
|
||||
commandLine.AppendSwitch("disable-gpu-compositing");
|
||||
commandLine.AppendSwitch("disable-features", "VizDisplayCompositor");
|
||||
commandLine.AppendSwitch("ppapi-flash-version", "99.0.0.999");
|
||||
commandLine.AppendSwitch("ppapi-flash-path", @"PepperFlash\pepflashplayer.dll");
|
||||
//}
|
||||
|
||||
+7
-3
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
@@ -767,4 +771,4 @@
|
||||
private DevExpress.XtraBars.PopupMenu pmFP;
|
||||
private DevExpress.XtraBars.BarManager barManager2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,55 @@ namespace Lskj.PubAccraditation
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
PrintUtil.OnAfterPrint -= OnReportPrintAfter;
|
||||
|
||||
MyControl control = ControlObj;
|
||||
ControlObj = null;
|
||||
if (control != null)
|
||||
{
|
||||
control.OnDataSourceBindCallBack -=
|
||||
OnControlObjOnDataSourceBindCallBack;
|
||||
control.OnDataFileRefrshCallBack -= OnDataFileRefrshFile;
|
||||
control.Dispose();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (gridBillInfo != null)
|
||||
{
|
||||
TreeGridControlEx treeGrid =
|
||||
gridBillInfo as TreeGridControlEx;
|
||||
if (treeGrid != null)
|
||||
{
|
||||
treeGrid.OnDataSourceBindCallBack -=
|
||||
OnGridBillInfoOnDataSourceBindCallBack;
|
||||
}
|
||||
else
|
||||
{
|
||||
gridBillInfo.OnDataSourceBindCallBack -=
|
||||
OnGridBillInfoOnDataSourceBindCallBack;
|
||||
}
|
||||
gridBillInfo.ParentControl = null;
|
||||
}
|
||||
if (SysModel != null && SysModel.DataCaches != null)
|
||||
{
|
||||
SysModel.DataCaches.Remove(this);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// A partially disposed child must not stop form cleanup.
|
||||
}
|
||||
}
|
||||
#region 公有变量
|
||||
|
||||
/// <summary>
|
||||
@@ -70,6 +119,7 @@ namespace Lskj.PubAccraditation
|
||||
/// 主表控件
|
||||
/// </summary>
|
||||
public MyControl ControlObj;
|
||||
private bool mResourcesReleased;
|
||||
/// <summary>
|
||||
/// 是否是Brp模块加载审核明细
|
||||
/// </summary>
|
||||
@@ -385,16 +435,6 @@ namespace Lskj.PubAccraditation
|
||||
{
|
||||
return BaseModuleImpl.GetControlLocation(billAuditModelTask.Result.FormKey, dynamicModel.ModuleCode);
|
||||
}));
|
||||
Task<MyControl> controlObjTask = cachesDic.AddTask(this, "ControlObj", new Task<MyControl>(() =>
|
||||
{
|
||||
MyControl myControl = new MyControl();
|
||||
myControl.Model = SysModel;
|
||||
myControl.PrimaryValue = dynamicModel.BillDocumentId;
|
||||
cachesDic.AddTask(myControl, "DynamicModel", dynamicModelTask);
|
||||
cachesDic.AddTask(myControl, "ControlsTable", controlLocationTask);
|
||||
myControl.GetControlDataCaches(cachesDic);
|
||||
return myControl;
|
||||
}));
|
||||
Task<DataTable> detailColumnsTask = cachesDic.AddTask(gridBillInfo, "DetailColumns", new Task<DataTable>(() =>
|
||||
{
|
||||
return BillImpl.GetDetailColumns(dynamicModel.ModuleCode);
|
||||
@@ -980,14 +1020,26 @@ namespace Lskj.PubAccraditation
|
||||
{
|
||||
Dictionary<object, Hashtable> dataCaches = SysModel != null ? SysModel.DataCaches : null;
|
||||
// 初始化表头
|
||||
bool controlCreated = false;
|
||||
if (!dataCaches.GetValue(this, "ControlObj", out this.ControlObj))
|
||||
{
|
||||
this.ControlObj = new MyControl();
|
||||
controlCreated = true;
|
||||
}
|
||||
if (!dataCaches.GetValue(this, "ControlLocation", out DataTable dtControlLocation))
|
||||
{
|
||||
dtControlLocation = BaseModuleImpl.GetControlLocation(this.BillModelObj.FormKey, this.SysModel.ModuleCode);
|
||||
}
|
||||
if (controlCreated && dataCaches != null)
|
||||
{
|
||||
DynamicModel controlModel = SysModel;
|
||||
DataTable controlsTable = dtControlLocation;
|
||||
dataCaches.AddTask(ControlObj, "DynamicModel",
|
||||
new Task<DynamicModel>(() => controlModel));
|
||||
dataCaches.AddTask(ControlObj, "ControlsTable",
|
||||
new Task<DataTable>(() => controlsTable));
|
||||
ControlObj.GetControlDataCaches(dataCaches);
|
||||
}
|
||||
this.ControlObj.PrimaryValue = this.SysModel.BillDocumentId;
|
||||
this.ControlObj.isAuditMain = true;
|
||||
this.ControlObj.InitControl(dtControlLocation, this.pl_left_top);
|
||||
|
||||
@@ -26,6 +26,7 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -89,6 +90,7 @@ namespace Lskj.PubBill
|
||||
/// </summary>
|
||||
private DataTable _detailColumns;
|
||||
private bool IsCopying = false;
|
||||
private bool _moduleResourcesReleased;
|
||||
|
||||
|
||||
protected DataRow BillRowItem;
|
||||
@@ -260,6 +262,155 @@ namespace Lskj.PubBill
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases runtime objects created by the bill module. Cleanup is
|
||||
/// idempotent and best-effort so it cannot change the close result.
|
||||
/// </summary>
|
||||
public void ReleaseModuleResources()
|
||||
{
|
||||
if (_moduleResourcesReleased)
|
||||
return;
|
||||
_moduleResourcesReleased = true;
|
||||
|
||||
TryRelease(() => PrintUtil.OnAfterPrint -= new EventHandler(OnReportPrintAfter), "打印回调");
|
||||
TryRelease(ReleaseModuleEvents, "模块事件");
|
||||
TryRelease(ReleaseModuleDataSources, "模块数据源");
|
||||
TryRelease(ReleaseRuntimeCollections, "运行时集合");
|
||||
|
||||
BillRowItem = null;
|
||||
ControlObj = null;
|
||||
BillModel = null;
|
||||
SysModel = null;
|
||||
SumGridColumn = null;
|
||||
ScanCodeTextEdit = null;
|
||||
InitialSelectionTab = null;
|
||||
_imageEdit = null;
|
||||
_waterMark = null;
|
||||
_itemImport = null;
|
||||
_itemImportUpdate = null;
|
||||
}
|
||||
|
||||
private void ReleaseModuleEvents()
|
||||
{
|
||||
if (ScanCodeTextEdit != null)
|
||||
ScanCodeTextEdit.KeyDown -= Text_KeyDown;
|
||||
|
||||
if (gcMain != null)
|
||||
{
|
||||
gcMain.OnAfterLinkCilk -= OnAfterLinkCilkCall;
|
||||
gcMain.OnAllAfterParseCallBack -= OnAllAfterParseCallBack;
|
||||
if (gcMain.GridControl != null)
|
||||
gcMain.GridControl.DataSourceChanged -= OnGcMainDataSourceChanged;
|
||||
if (gcMain.GridView != null)
|
||||
{
|
||||
gcMain.GridView.KeyDown -= OnToWithdraw;
|
||||
gcMain.GridView.ShowingEditor -= OnGridViewShowingEditor;
|
||||
gcMain.GridView.MouseDown -= GridView_MouseDown;
|
||||
gcMain.GridView.FocusedRowChanged -= GridView_FocusedRowChanged;
|
||||
gcMain.GridView.InitNewRow -= OnGridViewInitNewRow;
|
||||
gcMain.GridView.CellValueChanged -= OnGridViewCellValueChanged;
|
||||
gcMain.GridView.RowCellClick -= OngcMainRowCellClick;
|
||||
}
|
||||
}
|
||||
|
||||
if (tb_buttom != null)
|
||||
{
|
||||
tb_buttom.OnDetailSaveGridCallBack -= Tab_OnDetailSaveGridCallBack;
|
||||
tb_buttom.BillDetailRightGridCallBack -= Tab_OnDetailSaveGridCallBack;
|
||||
tb_buttom.OnRightCallback -= OnButtomRightCallBack;
|
||||
if (tb_buttom.TabControlObj != null)
|
||||
tb_buttom.TabControlObj.SelectedPageChanged -= TabControlObj_SelectedPageChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseModuleDataSources()
|
||||
{
|
||||
foreach (System.Windows.Forms.Control control in EnumerateChildControls(this).ToList())
|
||||
{
|
||||
GridControlEx grid = control as GridControlEx;
|
||||
if (grid != null)
|
||||
{
|
||||
TreeGridControlEx treeGrid = grid as TreeGridControlEx;
|
||||
if (treeGrid != null && treeGrid.TreeListObj != null)
|
||||
treeGrid.TreeListObj.DataSource = null;
|
||||
if (grid.GridControl != null)
|
||||
grid.GridControl.DataSource = null;
|
||||
}
|
||||
|
||||
XtraTabPage tabPage = control as XtraTabPage;
|
||||
if (tabPage != null)
|
||||
tabPage.Tag = null;
|
||||
}
|
||||
|
||||
if (_imageEdit != null && _imageEdit.TextEdit != null)
|
||||
_imageEdit.TextEdit.Image = null;
|
||||
if (cb_input != null)
|
||||
cb_input.Properties.Items.Clear();
|
||||
if (cb_templete != null)
|
||||
cb_templete.Properties.Items.Clear();
|
||||
}
|
||||
|
||||
private static IEnumerable<System.Windows.Forms.Control> EnumerateChildControls(
|
||||
System.Windows.Forms.Control root)
|
||||
{
|
||||
if (root == null)
|
||||
yield break;
|
||||
yield return root;
|
||||
foreach (System.Windows.Forms.Control child in root.Controls)
|
||||
foreach (System.Windows.Forms.Control nested in EnumerateChildControls(child))
|
||||
yield return nested;
|
||||
}
|
||||
|
||||
private void ReleaseRuntimeCollections()
|
||||
{
|
||||
foreach (BillModuleModel model in BillModuleModelDic.Values.ToList())
|
||||
{
|
||||
if (model == null)
|
||||
continue;
|
||||
model.SourceControl = null;
|
||||
model.SourceDetailControl = null;
|
||||
model.SourceDetailDetailControl = null;
|
||||
model.SourceModel = null;
|
||||
}
|
||||
BillModuleModelDic.Clear();
|
||||
pageNumKey.Clear();
|
||||
foreach (Dictionary<int, DataRow> rows in ToWithdrawRows)
|
||||
if (rows != null)
|
||||
rows.Clear();
|
||||
ToWithdrawRows.Clear();
|
||||
ChangeColorRow.Clear();
|
||||
DateColumnList.Clear();
|
||||
itemCommonList.Clear();
|
||||
ColorHandles.Clear();
|
||||
if (DetailMappingField != null)
|
||||
DetailMappingField.Clear();
|
||||
if (_printSaveParams != null)
|
||||
_printSaveParams.Clear();
|
||||
|
||||
if (_detailColumns != null)
|
||||
{
|
||||
_detailColumns.Dispose();
|
||||
_detailColumns = null;
|
||||
}
|
||||
if (SaveCondTab != null)
|
||||
{
|
||||
SaveCondTab.Dispose();
|
||||
SaveCondTab = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryRelease(Action release, string operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
release();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.WriteLine("释放单据模块资源失败[" + operation + "]:" + exception);
|
||||
}
|
||||
}
|
||||
|
||||
#region 初始化操作
|
||||
/// <summary>
|
||||
/// <para>说明:窗口加载</para>
|
||||
|
||||
@@ -209,5 +209,21 @@ namespace Lskj.PubBill
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
base.OnFormClosed(e);
|
||||
this.FormClosing -= OnClose;
|
||||
this.Activated -= FrmMain_Activated;
|
||||
try
|
||||
{
|
||||
if (billModule1 != null)
|
||||
billModule1.ReleaseModuleResources();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("释放单据窗口资源失败:" + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,30 @@ namespace Lskj.PubBrower
|
||||
this.SubForm = main;
|
||||
this.SubForm.Text = moduleModel.FormText;
|
||||
main.PubBrowerModel = moduleModel;
|
||||
main.OnLoad();
|
||||
|
||||
// CEF must be created after the caller has established the final
|
||||
// WinForms owner/parent hierarchy and the form HWND exists.
|
||||
if (moduleModel.downLoadFlag == 1)
|
||||
{
|
||||
main.OnLoad();
|
||||
}
|
||||
else
|
||||
{
|
||||
EventHandler shown = null;
|
||||
shown = delegate
|
||||
{
|
||||
main.Shown -= shown;
|
||||
try
|
||||
{
|
||||
main.OnLoad();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogUtil.WriteError("Lskj.PubBrower.dll--初始化错误-->" + obj.ToString(), ex);
|
||||
}
|
||||
};
|
||||
main.Shown += shown;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -100,8 +100,8 @@ namespace Lskj.PubBrower
|
||||
previewFrm previewFrm = new previewFrm();
|
||||
previewFrm.moduleWebView.PubBrowerModel = this.PubBrowerModel;
|
||||
previewFrm.Dock = DockStyle.Fill;
|
||||
previewFrm.OnLoad(url, RightKeyFlag);
|
||||
this.Controls.Add(previewFrm);
|
||||
previewFrm.OnLoad(url, RightKeyFlag);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace Lskj.PubBrower
|
||||
public previewFrm()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SizeChanged += OnSizeChanged;
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>说明:窗口加载</para>
|
||||
@@ -48,18 +47,5 @@ namespace Lskj.PubBrower
|
||||
MessageUtil.Show(Message, ex.Message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 窗体大小改变时
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnSizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (this.moduleWebView.cefBrowserSettings != null)
|
||||
{
|
||||
var handle = this.moduleWebView.cefBrowserSettings.GetHost().GetWindowHandle();
|
||||
this.moduleWebView.ResizeWindow(handle, this.Width, this.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,30 @@ namespace Lskj.PubBrower2
|
||||
this.SubForm = main;
|
||||
this.SubForm.Text = moduleModel.FormText;
|
||||
main.PubBrowerModel = moduleModel;
|
||||
main.OnLoad();
|
||||
|
||||
// CEF must be created after the caller has established the final
|
||||
// WinForms owner/parent hierarchy and the form HWND exists.
|
||||
if (moduleModel.downLoadFlag == 1)
|
||||
{
|
||||
main.OnLoad();
|
||||
}
|
||||
else
|
||||
{
|
||||
EventHandler shown = null;
|
||||
shown = delegate
|
||||
{
|
||||
main.Shown -= shown;
|
||||
try
|
||||
{
|
||||
main.OnLoad();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogUtil.WriteError("Lskj.PubBrower2.dll--初始化错误-->" + obj.ToString(), ex);
|
||||
}
|
||||
};
|
||||
main.Shown += shown;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -95,8 +95,8 @@ namespace Lskj.PubBrower2
|
||||
previewFrm previewFrm = new previewFrm();
|
||||
previewFrm.moduleWebView.PubBrowerModel = this.PubBrowerModel;
|
||||
previewFrm.Dock = DockStyle.Fill;
|
||||
previewFrm.OnLoad(url, RightKeyFlag);
|
||||
this.Controls.Add(previewFrm);
|
||||
previewFrm.OnLoad(url, RightKeyFlag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace Lskj.PubBrower2
|
||||
public previewFrm()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.SizeChanged += OnSizeChanged;
|
||||
}
|
||||
/// <summary>
|
||||
/// <para>说明:窗口加载</para>
|
||||
@@ -49,18 +48,5 @@ namespace Lskj.PubBrower2
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗体大小改变时
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnSizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (this.moduleWebView.cefBrowserSettings != null)
|
||||
{
|
||||
var handle = this.moduleWebView.cefBrowserSettings.GetHost().GetWindowHandle();
|
||||
this.moduleWebView.ResizeWindow(handle, this.Width, this.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,24 @@ namespace Lskj.PubModelAdd
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
MyControl search = _leftGridSearchObj;
|
||||
_leftGridSearchObj = null;
|
||||
if (search != null)
|
||||
{
|
||||
search.OnDataSourceBindCallBack -=
|
||||
OnLeftControlObjDataSourceBindCallBack;
|
||||
search.Dispose();
|
||||
}
|
||||
}
|
||||
#region 私有变量
|
||||
/// <summary>
|
||||
/// 模块初始化完成
|
||||
@@ -42,6 +60,7 @@ namespace Lskj.PubModelAdd
|
||||
/// 左侧表格查询条件
|
||||
/// </summary>
|
||||
private MyControl _leftGridSearchObj;
|
||||
private bool mResourcesReleased;
|
||||
#endregion
|
||||
#region 公共变量
|
||||
/// <summary>
|
||||
|
||||
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,24 @@ namespace Lskj.PubModelAdd2
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
MyControl search = _leftGridSearchObj;
|
||||
_leftGridSearchObj = null;
|
||||
if (search != null)
|
||||
{
|
||||
search.OnDataSourceBindCallBack -=
|
||||
OnLeftControlObjDataSourceBindCallBack;
|
||||
search.Dispose();
|
||||
}
|
||||
}
|
||||
#region 私有变量
|
||||
/// <summary>
|
||||
/// 模块初始化完成
|
||||
@@ -45,6 +63,7 @@ namespace Lskj.PubModelAdd2
|
||||
/// 左侧表格查询条件
|
||||
/// </summary>
|
||||
private MyControl _leftGridSearchObj;
|
||||
private bool mResourcesReleased;
|
||||
#endregion
|
||||
#region 公共变量
|
||||
/// <summary>
|
||||
|
||||
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,24 @@ namespace Lskj.PubModelAdd3
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ReleaseResourcesForDispose()
|
||||
{
|
||||
if (mResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mResourcesReleased = true;
|
||||
MyControl search = _leftGridSearchObj;
|
||||
_leftGridSearchObj = null;
|
||||
if (search != null)
|
||||
{
|
||||
search.OnDataSourceBindCallBack -=
|
||||
OnLeftControlObjDataSourceBindCallBack;
|
||||
search.Dispose();
|
||||
}
|
||||
}
|
||||
#region 私有变量
|
||||
/// <summary>
|
||||
/// 模块初始化完成
|
||||
@@ -45,6 +63,7 @@ namespace Lskj.PubModelAdd3
|
||||
/// 左侧表格查询条件
|
||||
/// </summary>
|
||||
private MyControl _leftGridSearchObj;
|
||||
private bool mResourcesReleased;
|
||||
#endregion
|
||||
#region 公共变量
|
||||
/// <summary>
|
||||
|
||||
Generated
+7
-3
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
ReleaseResourcesForDispose();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
@@ -280,4 +284,4 @@
|
||||
private DevExpress.XtraEditors.SimpleButton btnShowAll;
|
||||
private DevExpress.XtraEditors.SimpleButton btnRefresh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Lskj.PubSpec2
|
||||
/// 表格列
|
||||
/// </summary>
|
||||
private DataTable _gridColumns;
|
||||
private GridDragTree _dragTree;
|
||||
|
||||
/// <summary>
|
||||
/// 模块对象
|
||||
@@ -56,6 +57,17 @@ namespace Lskj.PubSpec2
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ReleaseResourcesForDispose()
|
||||
{
|
||||
GridDragTree dragTree = _dragTree;
|
||||
_dragTree = null;
|
||||
if (dragTree != null)
|
||||
{
|
||||
dragTree.OnDragComplete -= OnDragCompleted;
|
||||
dragTree.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>说明:窗口加载</para>
|
||||
/// <para>创建人:龚宇超</para>
|
||||
@@ -229,9 +241,9 @@ namespace Lskj.PubSpec2
|
||||
this.gcMain.Model = this.Model;
|
||||
this._gridColumns = BaseModuleImpl.GetBaseGridColumns(this.Model.ModuleCode);
|
||||
|
||||
GridDragTree dragTree = new GridDragTree(this.gcMain.GridView, this.treeLeft.TreeView);
|
||||
dragTree.CanDragParentNode = true;
|
||||
dragTree.OnDragComplete += new GridDragTreeCompleteEventHandler(OnDragCompleted);
|
||||
this._dragTree = new GridDragTree(this.gcMain.GridView, this.treeLeft.TreeView);
|
||||
this._dragTree.CanDragParentNode = true;
|
||||
this._dragTree.OnDragComplete += new GridDragTreeCompleteEventHandler(OnDragCompleted);
|
||||
|
||||
this.gcMain.IsSpecModel = true;
|
||||
this.gcMain.SetEditColumns(this._gridColumns);
|
||||
|
||||
Generated
+6
-2
@@ -13,9 +13,13 @@
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
if (disposing)
|
||||
{
|
||||
components.Dispose();
|
||||
DisposeReportGridViews();
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ using Lskj.Business.Impl;
|
||||
using Lskj.Business;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Lskj.Report
|
||||
{
|
||||
@@ -34,9 +36,19 @@ namespace Lskj.Report
|
||||
/// </summary>
|
||||
public DynamicReportModel Model;
|
||||
|
||||
private readonly HashSet<DevExpress.XtraGrid.Views.Base.BaseView>
|
||||
mPreexistingGridLocalizerViews = CaptureGridLocalizerViews();
|
||||
private readonly HashSet<DevExpress.XtraGrid.Views.Base.BaseView>
|
||||
mReportGridLocalizerViews =
|
||||
new HashSet<DevExpress.XtraGrid.Views.Base.BaseView>();
|
||||
private bool mReportGridResourcesReleased;
|
||||
private int mDisposedReportGridViewCount;
|
||||
private int mRemovedGridLocalizerHandlerCount;
|
||||
|
||||
public FrmMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Disposed += OnFrmMainDisposed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,6 +78,7 @@ namespace Lskj.Report
|
||||
|
||||
this.mControl.Details = details;
|
||||
this.mControl.InitControls(Model);
|
||||
CaptureReportGridLocalizerViews();
|
||||
this.FormClosing += new FormClosingEventHandler(OnClose);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -86,7 +99,570 @@ namespace Lskj.Report
|
||||
|
||||
private void OnClose(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
WriteReportLifecycleDiagnostics("closing-before-close-module");
|
||||
this.mControl.CloseModule();
|
||||
WriteReportLifecycleDiagnostics("closing-after-close-module");
|
||||
}
|
||||
|
||||
private void OnFrmMainDisposed(object sender, EventArgs e)
|
||||
{
|
||||
DisposeReportGridViews();
|
||||
WriteReportLifecycleDiagnostics(
|
||||
"disposed-event;disposedGridViews=" +
|
||||
mDisposedReportGridViewCount +
|
||||
";gridLocalizerRemoved=" +
|
||||
mRemovedGridLocalizerHandlerCount);
|
||||
mReportGridLocalizerViews.Clear();
|
||||
mPreexistingGridLocalizerViews.Clear();
|
||||
this.FormClosing -= OnClose;
|
||||
this.Disposed -= OnFrmMainDisposed;
|
||||
|
||||
DynamicReportModel model = this.Model;
|
||||
this.Model = null;
|
||||
if (model == null || model.DataCaches == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
model.DataCaches.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport);
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeReportGridViews()
|
||||
{
|
||||
if (mReportGridResourcesReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mReportGridResourcesReleased = true;
|
||||
WriteReportLifecycleDiagnostics("dispose-before-gridviews");
|
||||
CaptureReportGridLocalizerViews();
|
||||
if (this.mControl != null)
|
||||
{
|
||||
this.mControl.ReleaseResourcesForDispose();
|
||||
}
|
||||
|
||||
HashSet<DevExpress.XtraGrid.Views.Base.BaseView> disposedViews =
|
||||
new HashSet<DevExpress.XtraGrid.Views.Base.BaseView>();
|
||||
int disposeErrorCount = 0;
|
||||
int detachedDataSourceCount = 0;
|
||||
foreach (System.Windows.Forms.Control control in
|
||||
EnumerateControls(this.mControl))
|
||||
{
|
||||
DevExpress.XtraGrid.GridControl gridControl =
|
||||
control as DevExpress.XtraGrid.GridControl;
|
||||
if (gridControl != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (gridControl.DataSource != null)
|
||||
{
|
||||
gridControl.DataSource = null;
|
||||
detachedDataSourceCount++;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
disposeErrorCount++;
|
||||
LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport);
|
||||
}
|
||||
|
||||
DevExpress.XtraGrid.Views.Base.BaseView[] views =
|
||||
gridControl.ViewCollection
|
||||
.Cast<DevExpress.XtraGrid.Views.Base.BaseView>()
|
||||
.ToArray();
|
||||
foreach (DevExpress.XtraGrid.Views.Base.BaseView view in views)
|
||||
{
|
||||
if (view == null || !disposedViews.Add(view))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
view.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
disposeErrorCount++;
|
||||
LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type controlType = control.GetType();
|
||||
if (controlType.FullName != null &&
|
||||
controlType.FullName.StartsWith(
|
||||
"DevExpress.XtraTreeList.",
|
||||
StringComparison.Ordinal))
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo dataSourceProperty =
|
||||
controlType.GetProperty(
|
||||
"DataSource",
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Public);
|
||||
if (dataSourceProperty != null &&
|
||||
dataSourceProperty.CanRead &&
|
||||
dataSourceProperty.CanWrite &&
|
||||
dataSourceProperty.GetValue(control, null) != null)
|
||||
{
|
||||
dataSourceProperty.SetValue(control, null, null);
|
||||
detachedDataSourceCount++;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
disposeErrorCount++;
|
||||
LogHelper.Instance.WriteError(ex, ResourceKeys.BaseReport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int trackedGridViews = mReportGridLocalizerViews.Count;
|
||||
int removedGridLocalizerHandlers =
|
||||
ReleaseTrackedGridLocalizerViews(disposedViews);
|
||||
mDisposedReportGridViewCount = disposedViews.Count;
|
||||
mRemovedGridLocalizerHandlerCount = removedGridLocalizerHandlers;
|
||||
WriteReportLifecycleDiagnostics(
|
||||
"dispose-after-gridviews;dispose-attempts=" +
|
||||
disposedViews.Count +
|
||||
";dispose-errors=" +
|
||||
disposeErrorCount +
|
||||
";detachedDataSources=" +
|
||||
detachedDataSourceCount +
|
||||
";trackedGridViews=" +
|
||||
trackedGridViews +
|
||||
";gridLocalizerRemoved=" +
|
||||
removedGridLocalizerHandlers);
|
||||
}
|
||||
|
||||
private void CaptureReportGridLocalizerViews()
|
||||
{
|
||||
HashSet<DevExpress.XtraGrid.Views.Base.BaseView> currentViews =
|
||||
CaptureGridLocalizerViews();
|
||||
foreach (DevExpress.XtraGrid.Views.Base.BaseView view in currentViews)
|
||||
{
|
||||
if (!mPreexistingGridLocalizerViews.Contains(view))
|
||||
{
|
||||
mReportGridLocalizerViews.Add(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int ReleaseTrackedGridLocalizerViews(
|
||||
HashSet<DevExpress.XtraGrid.Views.Base.BaseView> disposedViews)
|
||||
{
|
||||
foreach (DevExpress.XtraGrid.Views.Base.BaseView view in
|
||||
mReportGridLocalizerViews)
|
||||
{
|
||||
if (view == null ||
|
||||
(disposedViews != null && !disposedViews.Add(view)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
view.Dispose();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogHelper.Instance.WriteError(exception, ResourceKeys.BaseReport);
|
||||
}
|
||||
}
|
||||
|
||||
return RemoveGridLocalizerHandlers(mReportGridLocalizerViews);
|
||||
}
|
||||
|
||||
private static HashSet<DevExpress.XtraGrid.Views.Base.BaseView>
|
||||
CaptureGridLocalizerViews()
|
||||
{
|
||||
HashSet<DevExpress.XtraGrid.Views.Base.BaseView> result =
|
||||
new HashSet<DevExpress.XtraGrid.Views.Base.BaseView>();
|
||||
try
|
||||
{
|
||||
var activeLocalizer =
|
||||
DevExpress.XtraGrid.Localization.GridLocalizer.Active;
|
||||
if (activeLocalizer == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Type currentType = activeLocalizer.GetType();
|
||||
while (currentType != null && currentType != typeof(object))
|
||||
{
|
||||
FieldInfo[] fields = currentType.GetFields(
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Static |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.DeclaredOnly);
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
if (!typeof(Delegate).IsAssignableFrom(field.FieldType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object owner = field.IsStatic ? null : (object)activeLocalizer;
|
||||
Delegate current;
|
||||
try
|
||||
{
|
||||
current = field.GetValue(owner) as Delegate;
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (current == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (Delegate handler in current.GetInvocationList())
|
||||
{
|
||||
if (IsGridLocalizerHandler(handler))
|
||||
{
|
||||
result.Add(
|
||||
(DevExpress.XtraGrid.Views.Base.BaseView)
|
||||
handler.Target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Diagnostics cleanup must never interfere with form construction.
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int RemoveGridLocalizerHandlers(
|
||||
HashSet<DevExpress.XtraGrid.Views.Base.BaseView> targetViews)
|
||||
{
|
||||
if (targetViews == null || targetViews.Count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int removedCount = 0;
|
||||
try
|
||||
{
|
||||
var activeLocalizer =
|
||||
DevExpress.XtraGrid.Localization.GridLocalizer.Active;
|
||||
if (activeLocalizer == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Type currentType = activeLocalizer.GetType();
|
||||
while (currentType != null && currentType != typeof(object))
|
||||
{
|
||||
FieldInfo[] fields = currentType.GetFields(
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Static |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.DeclaredOnly);
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
if (!typeof(Delegate).IsAssignableFrom(field.FieldType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object owner = field.IsStatic ? null : (object)activeLocalizer;
|
||||
Delegate current;
|
||||
try
|
||||
{
|
||||
current = field.GetValue(owner) as Delegate;
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (current == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Delegate retained = null;
|
||||
int fieldRemovedCount = 0;
|
||||
foreach (Delegate handler in current.GetInvocationList())
|
||||
{
|
||||
DevExpress.XtraGrid.Views.Base.BaseView view =
|
||||
handler.Target as DevExpress.XtraGrid.Views.Base.BaseView;
|
||||
if (IsGridLocalizerHandler(handler) &&
|
||||
targetViews.Contains(view))
|
||||
{
|
||||
fieldRemovedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
retained = retained == null
|
||||
? handler
|
||||
: Delegate.Combine(retained, handler);
|
||||
}
|
||||
|
||||
if (fieldRemovedCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
field.SetValue(owner, retained);
|
||||
removedCount += fieldRemovedCount;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Some DevExpress versions expose a read-only backing field.
|
||||
}
|
||||
}
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Diagnostics cleanup must never interfere with form disposal.
|
||||
}
|
||||
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
private static bool IsGridLocalizerHandler(Delegate handler)
|
||||
{
|
||||
return handler != null &&
|
||||
string.Equals(
|
||||
handler.Method.Name,
|
||||
"OnLocalizer_Changed",
|
||||
StringComparison.Ordinal) &&
|
||||
handler.Target is DevExpress.XtraGrid.Views.Base.BaseView;
|
||||
}
|
||||
|
||||
private void WriteReportLifecycleDiagnostics(string phase)
|
||||
{
|
||||
if (!IsReportDiagnosticsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.Instance.WriteLog(
|
||||
"REPORT_DIAGNOSTIC phase=" +
|
||||
(phase ?? string.Empty) +
|
||||
" " +
|
||||
GetReportGridDiagnostics(),
|
||||
"ResourceDiagnostics.Report");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Diagnostics must never interfere with module close/dispose.
|
||||
}
|
||||
}
|
||||
|
||||
private string GetReportGridDiagnostics()
|
||||
{
|
||||
int controlCount = 0;
|
||||
int gridControlCount = 0;
|
||||
int viewCount = 0;
|
||||
HashSet<DevExpress.XtraGrid.Views.Base.BaseView> views =
|
||||
new HashSet<DevExpress.XtraGrid.Views.Base.BaseView>();
|
||||
StringBuilder viewDetails = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
if (this.mControl != null)
|
||||
{
|
||||
foreach (System.Windows.Forms.Control control in EnumerateControls(this.mControl))
|
||||
{
|
||||
controlCount++;
|
||||
DevExpress.XtraGrid.GridControl gridControl =
|
||||
control as DevExpress.XtraGrid.GridControl;
|
||||
if (gridControl == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
gridControlCount++;
|
||||
foreach (DevExpress.XtraGrid.Views.Base.BaseView view in
|
||||
gridControl.ViewCollection.Cast<DevExpress.XtraGrid.Views.Base.BaseView>())
|
||||
{
|
||||
if (view == null || !views.Add(view))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
viewCount++;
|
||||
if (viewDetails.Length < 1800)
|
||||
{
|
||||
if (viewDetails.Length > 0)
|
||||
{
|
||||
viewDetails.Append(",");
|
||||
}
|
||||
|
||||
viewDetails.Append(SafeViewDescription(view));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
viewDetails.Append(",enumeration-error=");
|
||||
viewDetails.Append(exception.GetType().Name);
|
||||
}
|
||||
|
||||
return "formDisposed=" +
|
||||
this.IsDisposed +
|
||||
";controlCount=" +
|
||||
controlCount +
|
||||
";gridControlCount=" +
|
||||
gridControlCount +
|
||||
";viewCount=" +
|
||||
viewCount +
|
||||
";views=" +
|
||||
viewDetails +
|
||||
";gridLocalizer=" +
|
||||
DescribeGridLocalizer();
|
||||
}
|
||||
|
||||
private static string SafeViewDescription(
|
||||
DevExpress.XtraGrid.Views.Base.BaseView view)
|
||||
{
|
||||
try
|
||||
{
|
||||
return view.GetType().FullName +
|
||||
":" +
|
||||
(view.Name ?? string.Empty).Replace(";", ",");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "<view-description-error>";
|
||||
}
|
||||
}
|
||||
|
||||
private static string DescribeGridLocalizer()
|
||||
{
|
||||
try
|
||||
{
|
||||
var active =
|
||||
DevExpress.XtraGrid.Localization.GridLocalizer.Active;
|
||||
if (active == null)
|
||||
{
|
||||
return "active=null";
|
||||
}
|
||||
|
||||
StringBuilder handlers = new StringBuilder();
|
||||
int handlerCount = 0;
|
||||
Type currentType = active.GetType();
|
||||
while (currentType != null && currentType != typeof(object))
|
||||
{
|
||||
FieldInfo[] fields = currentType.GetFields(
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Static |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.DeclaredOnly);
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
if (!typeof(Delegate).IsAssignableFrom(field.FieldType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object owner = field.IsStatic ? null : (object)active;
|
||||
Delegate value = field.GetValue(owner) as Delegate;
|
||||
if (value == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (Delegate handler in value.GetInvocationList())
|
||||
{
|
||||
handlerCount++;
|
||||
if (handlers.Length < 1800)
|
||||
{
|
||||
if (handlers.Length > 0)
|
||||
{
|
||||
handlers.Append(",");
|
||||
}
|
||||
|
||||
string targetType = handler.Target == null
|
||||
? "static"
|
||||
: handler.Target.GetType().FullName;
|
||||
handlers.Append(field.Name.Replace(";", ","));
|
||||
handlers.Append("->");
|
||||
handlers.Append(targetType.Replace(";", ","));
|
||||
handlers.Append(".");
|
||||
handlers.Append(handler.Method.Name.Replace(";", ","));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
|
||||
return "activeType=" +
|
||||
active.GetType().FullName.Replace(";", ",") +
|
||||
";handlerCount=" +
|
||||
handlerCount +
|
||||
";handlers=" +
|
||||
handlers;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
return "localizer-error=" + exception.GetType().Name;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsReportDiagnosticsEnabled()
|
||||
{
|
||||
try
|
||||
{
|
||||
return File.Exists(
|
||||
Path.Combine(
|
||||
AppDomain.CurrentDomain.BaseDirectory,
|
||||
"Logs",
|
||||
"ResourceDiagnostics",
|
||||
"resource-diagnostics.enabled"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<System.Windows.Forms.Control> EnumerateControls(
|
||||
System.Windows.Forms.Control root)
|
||||
{
|
||||
if (root == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
yield return root;
|
||||
foreach (System.Windows.Forms.Control child in root.Controls)
|
||||
{
|
||||
foreach (System.Windows.Forms.Control nested in EnumerateControls(child))
|
||||
{
|
||||
yield return nested;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user