fix(winforms): release module grid resources

This commit is contained in:
2026-08-26 01:10:27 +08:00
parent 6cde5df2f2
commit 1e06682a12
8 changed files with 491 additions and 85 deletions
+162 -5
View File
@@ -629,6 +629,45 @@ namespace Lskj.Control
}
}
internal void ReleaseResourcesForDispose()
{
DisposeGridResources();
}
private void DetachGridViewEventHandlers()
{
if (gridView == null)
{
return;
}
gridView.CustomDrawRowIndicator -= OnGridViewCustomDrawRowIndicator;
gridView.SelectionChanged -= OnGridViewSelectionChanged;
gridView.FocusedRowObjectChanged -= OnGridViewFocusedRowObjectChanged;
gridView.BeforeLeaveRow -= OnGridView_BeforeLeaveRow;
gridView.CustomDrawCell -= OnGridViewCustomDrawCell;
gridView.CellValueChanged -= OnGridViewCellValueChanged;
gridView.DragObjectDrop -= OnGridViewDragObjectDrop;
gridView.CustomDrawGroupRow -= OnGridCustomDrawGroupRow;
gridView.KeyDown -= OnGridViewKeyDown;
gridView.DoubleClick -= OnGridViewDoubleClick;
gridView.Click -= OnGridViewClick;
gridView.Click -= OnGridView_Click;
gridView.CellMerge -= OnGridViewCellMerge;
gridView.CustomSummaryCalculate -= OnGridViewSummaryCalculate;
gridView.ShowFilterPopupCheckedListBox -= OnShowFilterPopupCheckedListBox;
gridView.DataSourceChanged -= OnGridDataSourceChanged;
gridView.RowCellStyle -= GridView_RowCellStyle;
gridView.CustomRowFilter -= GridView_CustomRowFilter;
gridView.EndGrouping -= GridView_EndGrouping;
gridView.ShowingEditor -= GridView_ShowingEditor;
gridView.MouseDown -= GridView_MouseDown;
gridView.MouseWheel -= GridView_MouseWheel;
gridView.PopupMenuShowing -= OnGridViewPopupMenuShowing;
gridView.EndSorting -= OnGridViewEndSorting;
LabPicUrlPreview.Detach(gridView);
}
private void DisposeGridResources()
{
if (_gridResourcesDisposed)
@@ -673,6 +712,11 @@ namespace Lskj.Control
ImageList.Clear();
RepeatedVerificationNames.Clear();
PromptMessage.Clear();
DetachGridViewEventHandlers();
DisposeGridViews();
DisposeRepositoryItems();
gridViewRightMenu?.ReleaseResourcesForDispose();
gridViewRightMenu = null;
ParentControl = null;
Model = null;
SysModel = null;
@@ -719,13 +763,126 @@ namespace Lskj.Control
private void DisposeRepositoryItems()
{
RepositoryItem[] repositoryItems = gridControl.RepositoryItems
.Cast<RepositoryItem>()
.ToArray();
gridControl.RepositoryItems.Clear();
RepositoryItem[] repositoryItems;
try
{
if (gridControl == null)
{
return;
}
repositoryItems = gridControl.RepositoryItems
.Cast<RepositoryItem>()
.ToArray();
}
catch
{
// The inner control may already have released its repository collection.
return;
}
DisposeRepositoryButtonForms(repositoryItems);
try
{
gridControl.RepositoryItems.Clear();
}
catch
{
// Continue disposing the captured items.
}
foreach (RepositoryItem repositoryItem in repositoryItems)
{
repositoryItem.Dispose();
try
{
repositoryItem.Dispose();
}
catch
{
// Continue releasing the remaining repository items.
}
}
}
private static void DisposeRepositoryButtonForms(IEnumerable<RepositoryItem> repositoryItems)
{
HashSet<Form> forms = new HashSet<Form>();
foreach (RepositoryItemButtonEdit buttonEditor in repositoryItems.OfType<RepositoryItemButtonEdit>())
{
foreach (EditorButton button in buttonEditor.Buttons)
{
Form form = button.Tag as Form;
if (form == null)
{
continue;
}
button.Tag = null;
forms.Add(form);
}
}
foreach (Form form in forms)
{
try
{
form.Dispose();
}
catch
{
// A lookup window must not prevent its owning grid from being released.
}
}
}
private void DisposeGridViews()
{
HashSet<BaseView> views = new HashSet<BaseView>();
if (gridView != null)
{
views.Add(gridView);
}
try
{
if (gridControl != null)
{
foreach (BaseView view in gridControl.ViewCollection.Cast<BaseView>().ToArray())
{
if (view != null)
{
views.Add(view);
}
}
}
}
catch
{
// The inner control may already be disposing its view collection.
}
foreach (BaseView view in views)
{
GridView disposableGridView = view as GridView;
if (disposableGridView != null)
{
try
{
StaticControl.ReleaseGridViewReferences(disposableGridView);
}
catch
{
// Static cleanup is best-effort; the view must still be disposed.
}
}
try
{
view.Dispose();
}
catch
{
// Continue releasing the remaining views during control disposal.
}
}
}