using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.BandedGrid;
using DevExpress.XtraTab;
using Lskj.Control.ZKFinger;
using Lskj.Model;
using Lskj.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
using WinFormsControl = System.Windows.Forms.Control;
namespace Lskj.Control.Model
{
///
/// WinForms-owned runtime state. A module registers the objects it creates
/// while it is being opened; closing a module disposes only that module's
/// scope. This deliberately has no control-tree traversal.
///
public static class StaticControl
{
private static readonly object ModuleRegistrySync = new object();
///
/// Owns cleanup callbacks for one opened module instance.
///
public sealed class ModuleResourceScope : IDisposable
{
private sealed class Registration
{
internal readonly object Owner;
internal readonly Action Cleanup;
internal Registration(object owner, Action cleanup)
{
Owner = owner;
Cleanup = cleanup;
}
}
private readonly object _sync = new object();
private readonly List _registrations =
new List();
private bool _disposed;
public ModuleResourceScope(string moduleId)
{
ModuleId = moduleId ?? string.Empty;
TrackModuleScope(this);
}
public string ModuleId { get; private set; }
public bool IsDisposed
{
get
{
lock (_sync)
{
return _disposed;
}
}
}
public void Register(object owner, Action cleanup)
{
if (cleanup == null)
return;
bool runImmediately = false;
lock (_sync)
{
if (_disposed)
runImmediately = true;
else
_registrations.Add(new Registration(owner, cleanup));
}
if (runImmediately)
InvokeCleanup(cleanup);
}
public void Unregister(object owner)
{
lock (_sync)
{
for (int index = _registrations.Count - 1; index >= 0; index--)
if (ReferenceEquals(_registrations[index].Owner, owner))
_registrations.RemoveAt(index);
}
}
public void Dispose()
{
List registrations;
lock (_sync)
{
if (_disposed)
return;
_disposed = true;
registrations = new List(_registrations);
_registrations.Clear();
}
// Reverse order mirrors normal ownership: the last registered
// helper is released before its owner.
for (int index = registrations.Count - 1; index >= 0; index--)
InvokeCleanup(registrations[index].Cleanup);
UntrackModuleScope(this);
}
private static void InvokeCleanup(Action cleanup)
{
try
{
cleanup();
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine(
"释放模块登记资源失败:" + exception);
}
}
}
private static void TrackModuleScope(ModuleResourceScope scope)
{
if (scope == null)
return;
lock (ActiveModuleScopesSync)
{
if (!ActiveModuleScopes.Contains(scope))
ActiveModuleScopes.Add(scope);
}
}
private static void UntrackModuleScope(ModuleResourceScope scope)
{
if (scope == null)
return;
lock (ActiveModuleScopesSync)
{
ActiveModuleScopes.Remove(scope);
}
}
///
/// Releases scopes created by legacy page-open paths that are not
/// present in Manager.ModuleScopes. Dispose is idempotent, so this is
/// safe to call after the managed module close pass.
///
public static void CompleteAllModuleResourceScopes()
{
ModuleResourceScope[] scopes;
lock (ActiveModuleScopesSync)
{
scopes = ActiveModuleScopes.ToArray();
}
foreach (ModuleResourceScope scope in scopes)
{
if (scope != null)
scope.Dispose();
}
}
private sealed class ScopeCookie : IDisposable
{
private readonly ModuleResourceScope _previous;
private bool _disposed;
internal ScopeCookie(ModuleResourceScope previous)
{
_previous = previous;
}
public void Dispose()
{
if (_disposed)
return;
_disposed = true;
_currentModuleScope = _previous;
}
}
[ThreadStatic]
private static ModuleResourceScope _currentModuleScope;
// The table does not keep a disposed control alive. A short parent
// chain lookup is used only for controls created after PushModuleScope;
// there is never a global scan of the module's control tree.
private static readonly ConditionalWeakTable
ModuleScopeOwners =
new ConditionalWeakTable();
private static readonly object ActiveModuleScopesSync = new object();
private static readonly List ActiveModuleScopes =
new List();
private static readonly Dictionary ModuleSearchControls =
new Dictionary(StringComparer.OrdinalIgnoreCase);
public static ModuleResourceScope CurrentModuleScope
{
get { return _currentModuleScope; }
}
public static IDisposable PushModuleScope(ModuleResourceScope scope)
{
ModuleResourceScope previous = _currentModuleScope;
_currentModuleScope = scope != null && !scope.IsDisposed ? scope : null;
return new ScopeCookie(previous);
}
private static ModuleResourceScope GetLiveCurrentModuleScope()
{
return _currentModuleScope != null && !_currentModuleScope.IsDisposed
? _currentModuleScope
: null;
}
public static void AttachModuleScope(
WinFormsControl owner,
ModuleResourceScope scope)
{
if (owner == null || scope == null || scope.IsDisposed)
return;
ModuleScopeOwners.Remove(owner);
ModuleScopeOwners.Add(owner, scope);
}
///
/// Finds a scope attached to the owner or one of its parents without
/// falling back to the calling thread's current scope.
///
public static ModuleResourceScope FindAttachedModuleScope(
WinFormsControl owner)
{
ModuleResourceScope scope = FindParentModuleScope(owner);
if (scope != null)
return scope;
if (owner != null && ModuleScopeOwners.TryGetValue(owner, out scope) &&
scope != null && !scope.IsDisposed)
return scope;
return null;
}
public static ModuleResourceScope FindModuleScope(WinFormsControl owner)
{
ModuleResourceScope parentScope = FindParentModuleScope(owner);
if (parentScope != null)
return parentScope;
ModuleResourceScope scope;
if (owner != null && ModuleScopeOwners.TryGetValue(owner, out scope) &&
scope != null && !scope.IsDisposed)
return scope;
return _currentModuleScope != null && !_currentModuleScope.IsDisposed
? _currentModuleScope
: null;
}
///
/// Registers a page created by a legacy caller that cannot go through
/// Manager.AddModuleToTab. The page GUID is made the module GUID as
/// well, and the page/form roots are attached to one scope so the
/// normal close path can discover and dispose that scope.
///
public static ModuleResourceScope RegisterModulePage(
DllModule module,
XtraTabPage page,
Form form)
{
if (page == null)
return null;
string moduleId = Convert.ToString(page.Tag);
if (string.IsNullOrWhiteSpace(moduleId))
{
moduleId = Guid.NewGuid().ToString();
page.Tag = moduleId;
}
if (module != null)
{
module.Tag = moduleId;
if (form != null)
module.ModuleForm = form;
}
ModuleResourceScope scope = FindAttachedModuleScope(form) ??
FindAttachedModuleScope(page);
if (scope == null)
scope = new ModuleResourceScope(moduleId);
AttachModuleScope(page, scope);
AttachModuleScope(form, scope);
scope.Register(page, () =>
{
if (!page.IsDisposed)
page.Dispose();
});
if (form != null)
{
scope.Register(form, () =>
{
if (!form.IsDisposed)
form.Dispose();
});
}
return scope;
}
public static void RegisterModuleResource(
object owner,
Action cleanup)
{
RegisterModuleResource(owner, owner as WinFormsControl, cleanup);
}
public static void RegisterModuleResource(
object owner,
WinFormsControl context,
Action cleanup)
{
ModuleResourceScope scope = null;
if (context != null)
scope = FindModuleScope(context);
if (scope == null)
scope = GetLiveCurrentModuleScope();
if (scope != null)
scope.Register(owner, cleanup);
}
///
/// Registers one visual control as owned by its current module. A
/// ParentChanged subscription updates ownership when the same control
/// is explicitly moved to another live module; it never walks children.
///
public static void RegisterOwnedControl(WinFormsControl owner)
{
if (owner == null)
return;
// A legacy control can be constructed before it is parented. Keep
// one exact ParentChanged hook so ownership is registered as soon
// as it joins a module, including controls prepared off the UI path.
owner.ParentChanged -= OnOwnedControlParentChanged;
owner.ParentChanged += OnOwnedControlParentChanged;
ModuleResourceScope scope = GetLiveCurrentModuleScope();
if (scope == null)
scope = FindParentModuleScope(owner);
if (scope == null)
return;
ModuleResourceScope existing;
if (ModuleScopeOwners.TryGetValue(owner, out existing) &&
ReferenceEquals(existing, scope))
{
return;
}
AttachModuleScope(owner, scope);
scope.Register(owner, () =>
{
// A complete subtree may have been moved to another module
// without changing every descendant's Parent. Follow the live
// parent scope and leave that subtree owned by the open module.
ModuleResourceScope parentScope = FindParentModuleScope(owner);
if (parentScope != null && !ReferenceEquals(parentScope, scope))
{
ModuleResourceScope previous = _currentModuleScope;
_currentModuleScope = parentScope;
try
{
RegisterOwnedControl(owner);
}
finally
{
_currentModuleScope = previous;
}
return;
}
ModuleResourceScope current;
if (!ModuleScopeOwners.TryGetValue(owner, out current) ||
!ReferenceEquals(current, scope))
{
return;
}
owner.ParentChanged -= OnOwnedControlParentChanged;
ModuleScopeOwners.Remove(owner);
if (!owner.IsDisposed)
owner.Dispose();
});
}
private static ModuleResourceScope FindParentModuleScope(WinFormsControl owner)
{
for (WinFormsControl current = owner == null ? null : owner.Parent;
current != null;
current = current.Parent)
{
ModuleResourceScope scope;
if (ModuleScopeOwners.TryGetValue(current, out scope) &&
scope != null && !scope.IsDisposed)
return scope;
}
return null;
}
private static void OnOwnedControlParentChanged(object sender, EventArgs args)
{
WinFormsControl owner = sender as WinFormsControl;
if (owner == null || owner.IsDisposed)
return;
ModuleResourceScope parentScope = FindParentModuleScope(owner);
ModuleResourceScope currentScope;
if (parentScope != null &&
(!ModuleScopeOwners.TryGetValue(owner, out currentScope) ||
!ReferenceEquals(parentScope, currentScope)))
{
ModuleResourceScope previous = _currentModuleScope;
_currentModuleScope = parentScope;
try
{
RegisterOwnedControl(owner);
}
finally
{
_currentModuleScope = previous;
}
}
}
public static void RegisterModuleSearchControl(
WinFormsControl context,
MyControl searchControl)
{
if (searchControl == null)
return;
ModuleResourceScope scope = context == null
? GetLiveCurrentModuleScope()
: FindModuleScope(context);
if (scope == null || string.IsNullOrWhiteSpace(scope.ModuleId))
return;
string moduleId = scope.ModuleId;
lock (ModuleRegistrySync)
{
MyControl existing;
if (ModuleSearchControls.TryGetValue(moduleId, out existing))
{
if (ReferenceEquals(existing, searchControl))
return;
if (existing != null && !existing.IsDisposed)
return;
ModuleSearchControls.Remove(moduleId);
}
ModuleSearchControls[moduleId] = searchControl;
}
EventHandler disposed = null;
disposed = (sender, args) =>
{
searchControl.Disposed -= disposed;
lock (ModuleRegistrySync)
{
MyControl current;
if (ModuleSearchControls.TryGetValue(moduleId, out current) &&
ReferenceEquals(current, searchControl))
{
ModuleSearchControls.Remove(moduleId);
}
}
};
searchControl.Disposed += disposed;
scope.Register(searchControl, () =>
{
searchControl.Disposed -= disposed;
lock (ModuleRegistrySync)
{
MyControl current;
if (ModuleSearchControls.TryGetValue(moduleId, out current) &&
ReferenceEquals(current, searchControl))
{
ModuleSearchControls.Remove(moduleId);
}
}
});
}
public static MyControl FindModuleSearchControl(string moduleId)
{
if (string.IsNullOrWhiteSpace(moduleId))
return null;
lock (ModuleRegistrySync)
{
MyControl searchControl;
if (!ModuleSearchControls.TryGetValue(moduleId, out searchControl))
return null;
if (searchControl == null || searchControl.IsDisposed)
{
ModuleSearchControls.Remove(moduleId);
return null;
}
return searchControl;
}
}
public static void RegisterConditionPanel(
string key,
ModuleConditionsPanelEx panel)
{
if (panel == null)
return;
key = key ?? string.Empty;
lock (ModuleRegistrySync)
{
ModuleConditionsPanelEx previous;
if (ConditionsPanelDic.TryGetValue(key, out previous) &&
previous != null && previous.IsDisposed)
{
ConditionsPanelDic.Remove(key);
}
// A key can be reused by a second module instance. Never
// dispose the first live dialog from the second registration.
ConditionsPanelDic[key] = panel;
}
EventHandler disposed = null;
disposed = (sender, args) =>
{
panel.Disposed -= disposed;
lock (ModuleRegistrySync)
{
ModuleConditionsPanelEx current;
if (ConditionsPanelDic.TryGetValue(key, out current) &&
ReferenceEquals(current, panel))
{
ConditionsPanelDic.Remove(key);
}
}
};
panel.Disposed += disposed;
RegisterModuleResource(panel, panel, () =>
{
panel.Disposed -= disposed;
lock (ModuleRegistrySync)
{
ModuleConditionsPanelEx current;
if (ConditionsPanelDic.TryGetValue(key, out current) &&
ReferenceEquals(current, panel))
{
ConditionsPanelDic.Remove(key);
}
}
if (!panel.IsDisposed)
{
panel.Dispose();
}
});
}
public static void RegisterProtectedPage(XtraTabPage page)
{
if (page == null)
return;
lock (ModuleRegistrySync)
{
if (!DogVerifyModuleForms.Contains(page))
DogVerifyModuleForms.Add(page);
}
EventHandler disposed = null;
disposed = (sender, args) =>
{
page.Disposed -= disposed;
lock (ModuleRegistrySync)
{
DogVerifyModuleForms.Remove(page);
}
};
page.Disposed += disposed;
RegisterModuleResource(page, () =>
{
page.Disposed -= disposed;
lock (ModuleRegistrySync)
{
DogVerifyModuleForms.Remove(page);
}
});
}
public static void RegisterProtectedForm(IForm form)
{
if (form == null || form.SubForm == null)
return;
lock (ModuleRegistrySync)
{
if (!DogVerifyNoPageForms.Contains(form))
DogVerifyNoPageForms.Add(form);
}
Form subForm = form.SubForm;
EventHandler disposed = null;
disposed = (sender, args) =>
{
subForm.Disposed -= disposed;
lock (ModuleRegistrySync)
{
DogVerifyNoPageForms.Remove(form);
}
};
subForm.Disposed += disposed;
RegisterModuleResource(subForm, () =>
{
subForm.Disposed -= disposed;
lock (ModuleRegistrySync)
{
DogVerifyNoPageForms.Remove(form);
}
});
}
internal static void ReleaseGridViewReferences(GridView gridView)
{
if (gridView == null)
return;
GridDragGrid.DisposeRegistrations(
GridViewDragGridDic,
TargetViewDragGridDic,
gridView);
BandedGridDragGrid.DisposeRegistrations(
StaticBandedControl.BandedGridViewDragGridDic,
StaticBandedControl.BandedTargetViewDragGridDic,
gridView as BandedGridView,
gridView);
GridDragGrid.ClearSourceReferenceIfUnused(gridView);
if (ReferenceEquals(_RightMenuGridView, gridView))
RightMenuGridView = null;
}
private static void OnRightMenuGridViewDisposed(object sender, EventArgs args)
{
GridView view = sender as GridView;
if (ReferenceEquals(_RightMenuGridView, view))
RightMenuGridView = null;
}
private static void OnBomUnionPageDisposed(object sender, EventArgs args)
{
XtraTabPage page = sender as XtraTabPage;
if (ReferenceEquals(BomUnionPage, page))
SetBomUnionPage(null);
}
private static void OnRightMenuMyControlDisposed(object sender, EventArgs args)
{
MyControl control = sender as MyControl;
if (ReferenceEquals(RightMenuMyControl, control))
SetRightMenuMyControl(null);
}
private static void OnAddParentGridDisposed(object sender, EventArgs args)
{
GridControlEx grid = sender as GridControlEx;
if (ReferenceEquals(AddParentGrid.Value, grid))
SetAddParentGrid(new KeyValuePair());
}
///
/// 记录当前U盾权限窗口
///
public static List DogVerifyModuleForms =
new List();
public static List DogVerifyNoPageForms =
new List();
///
/// 模块打开时的条件界面
///
public static Dictionary ConditionsPanelDic =
new Dictionary();
///
/// 表格拖拽类,key值为源表
///
public static Dictionary> GridViewDragGridDic =
new Dictionary>();
///
/// 表格拖拽类,key值为目标表
///
public static Dictionary> TargetViewDragGridDic =
new Dictionary>();
///
/// 当前拖拽源表格
///
public static GridView SourceDragGridView;
///
/// 指纹识别模块
///
public static FingerHelper fingerHelper;
public static KeyValuePair AddParentGrid =
new KeyValuePair();
public static void SetAddParentGrid(
KeyValuePair value)
{
if (ReferenceEquals(AddParentGrid.Value, value.Value) &&
string.Equals(AddParentGrid.Key, value.Key, StringComparison.Ordinal))
{
return;
}
GridControlEx previous = AddParentGrid.Value;
if (previous != null)
previous.Disposed -= OnAddParentGridDisposed;
AddParentGrid = value;
GridControlEx current = value.Value;
if (current == null)
return;
current.Disposed += OnAddParentGridDisposed;
RegisterModuleResource(current, () =>
{
current.Disposed -= OnAddParentGridDisposed;
if (ReferenceEquals(AddParentGrid.Value, current))
AddParentGrid = new KeyValuePair();
});
}
///
/// 当前右键点击时的表格
///
public static GridView _RightMenuGridView;
public static GridView RightMenuGridView
{
get { return _RightMenuGridView; }
set
{
if (ReferenceEquals(_RightMenuGridView, value))
{
Comprefix = string.Empty;
ReturnRowLisy.Clear();
return;
}
if (_RightMenuGridView != null)
_RightMenuGridView.Disposed -= OnRightMenuGridViewDisposed;
_RightMenuGridView = value;
Comprefix = string.Empty;
ReturnRowLisy.Clear();
if (value == null)
return;
value.Disposed += OnRightMenuGridViewDisposed;
RegisterModuleResource(
value,
value.GridControl as WinFormsControl,
() =>
{
value.Disposed -= OnRightMenuGridViewDisposed;
if (ReferenceEquals(_RightMenuGridView, value))
_RightMenuGridView = null;
});
}
}
///
/// bom附件修改时的关联页签
///
public static XtraTabPage BomUnionPage;
public static void SetBomUnionPage(XtraTabPage value)
{
if (ReferenceEquals(BomUnionPage, value))
return;
if (BomUnionPage != null)
BomUnionPage.Disposed -= OnBomUnionPageDisposed;
BomUnionPage = value;
if (value == null)
return;
value.Disposed += OnBomUnionPageDisposed;
RegisterModuleResource(value, () =>
{
value.Disposed -= OnBomUnionPageDisposed;
if (ReferenceEquals(BomUnionPage, value))
BomUnionPage = null;
});
}
///
/// 当前右键点击时的控件对象
///
public static MyControl RightMenuMyControl;
public static void SetRightMenuMyControl(MyControl value)
{
if (ReferenceEquals(RightMenuMyControl, value))
return;
if (RightMenuMyControl != null)
RightMenuMyControl.Disposed -= OnRightMenuMyControlDisposed;
RightMenuMyControl = value;
if (value == null)
return;
value.Disposed += OnRightMenuMyControlDisposed;
RegisterModuleResource(
value,
value.MainGridEx,
() =>
{
value.Disposed -= OnRightMenuMyControlDisposed;
if (ReferenceEquals(RightMenuMyControl, value))
RightMenuMyControl = null;
});
}
///
/// 当前右键点击时的表格的列前缀
///
public static string Comprefix;
///
/// 浏览器返回数据
///
public static List ReturnRowLisy = new List();
}
}