372 lines
15 KiB
C#
372 lines
15 KiB
C#
//using Prism.Ioc;
|
||
//using System;
|
||
//using System.Windows;
|
||
//using System.Windows.Controls;
|
||
//using System.Windows.Threading;
|
||
|
||
//namespace YY.Admin.Views.Control
|
||
//{
|
||
// /// <summary>
|
||
// /// TabContentView.xaml 的交互逻辑
|
||
// /// </summary>
|
||
// public partial class TabContentView : UserControl
|
||
// {
|
||
// public TabContentView()
|
||
// {
|
||
// InitializeComponent();
|
||
// this.Loaded += TabContentView_Loaded;
|
||
// this.Unloaded += TabContentView_Unloaded;
|
||
// }
|
||
|
||
// private bool _navigated = false;
|
||
|
||
// private void TabContentView_Loaded(object sender, RoutedEventArgs e)
|
||
// {
|
||
// try
|
||
// {
|
||
// if (string.IsNullOrWhiteSpace(RegionName))
|
||
// return;
|
||
|
||
// var regionManager = ContainerLocator.Current.Resolve<IRegionManager>();
|
||
|
||
// // 把内部 ContentControl 注册为 region(基于 RegionName)
|
||
// RegionManager.SetRegionName(PART_ContentHost, RegionName);
|
||
// RegionManager.SetRegionManager(PART_ContentHost, regionManager);
|
||
|
||
// // 延迟导航,确保 region 真正注册到 RegionManager 并且模板生成为止
|
||
// if (!_navigated && !string.IsNullOrEmpty(ViewName))
|
||
// {
|
||
// Dispatcher.BeginInvoke(new Action(() =>
|
||
// {
|
||
// try
|
||
// {
|
||
// // 再次检查 region 是否存在并执行导航
|
||
// if (regionManager.Regions.ContainsRegionWithName(RegionName))
|
||
// {
|
||
// regionManager.RequestNavigate(RegionName, ViewName);
|
||
// }
|
||
// else
|
||
// {
|
||
// // 如果 region 仍然不存在,尝试 RequestNavigate(Prism 通常会创建 region)
|
||
// regionManager.RequestNavigate(RegionName, ViewName);
|
||
// }
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// System.Diagnostics.Debug.WriteLine($"TabContentView 导航异常: {ex.Message}");
|
||
// }
|
||
// }), DispatcherPriority.Background);
|
||
|
||
// _navigated = true;
|
||
// }
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// System.Diagnostics.Debug.WriteLine($"TabContentView_Loaded 出错: {ex.Message}");
|
||
// }
|
||
// }
|
||
|
||
// private void TabContentView_Unloaded(object sender, RoutedEventArgs e)
|
||
// {
|
||
// try
|
||
// {
|
||
// if (!string.IsNullOrWhiteSpace(RegionName))
|
||
// {
|
||
// var regionManager = ContainerLocator.Current.Resolve<IRegionManager>();
|
||
// if (regionManager.Regions.ContainsRegionWithName(RegionName))
|
||
// {
|
||
// var region = regionManager.Regions[RegionName];
|
||
// region.RemoveAll();
|
||
// regionManager.Regions.Remove(RegionName);
|
||
// }
|
||
// }
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// System.Diagnostics.Debug.WriteLine($"TabContentView_Unloaded 清理异常: {ex.Message}");
|
||
// }
|
||
// }
|
||
|
||
// #region RegionName DP
|
||
// public static readonly DependencyProperty RegionNameProperty =
|
||
// DependencyProperty.Register(nameof(RegionName), typeof(string), typeof(TabContentView), new PropertyMetadata(null));
|
||
|
||
// public string RegionName
|
||
// {
|
||
// get => (string)GetValue(RegionNameProperty);
|
||
// set => SetValue(RegionNameProperty, value);
|
||
// }
|
||
// #endregion
|
||
|
||
// #region ViewName DP
|
||
// public static readonly DependencyProperty ViewNameProperty =
|
||
// DependencyProperty.Register(nameof(ViewName), typeof(string), typeof(TabContentView), new PropertyMetadata(null));
|
||
|
||
// public string ViewName
|
||
// {
|
||
// get => (string)GetValue(ViewNameProperty);
|
||
// set => SetValue(ViewNameProperty, value);
|
||
// }
|
||
// #endregion
|
||
// }
|
||
//}
|
||
using Prism.Ioc;
|
||
using System;
|
||
using System.Diagnostics;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Threading;
|
||
|
||
namespace YY.Admin.Views.Control
|
||
{
|
||
public partial class TabContentView : UserControl
|
||
{
|
||
public TabContentView()
|
||
{
|
||
InitializeComponent();
|
||
|
||
this.Loaded += TabContentView_Loaded;
|
||
this.Unloaded += TabContentView_Unloaded;
|
||
this.IsVisibleChanged += TabContentView_IsVisibleChanged;
|
||
this.DataContextChanged += TabContentView_DataContextChanged;
|
||
}
|
||
|
||
private bool _navigated = false;
|
||
private IRegionManager _regionManager;
|
||
private DispatcherOperation _pendingNavigationOp;
|
||
|
||
#region DPs
|
||
public static readonly DependencyProperty RegionNameProperty =
|
||
DependencyProperty.Register(nameof(RegionName), typeof(string), typeof(TabContentView), new PropertyMetadata(null, OnRegionOrViewNameChanged));
|
||
|
||
public string RegionName
|
||
{
|
||
get => (string)GetValue(RegionNameProperty);
|
||
set => SetValue(RegionNameProperty, value);
|
||
}
|
||
|
||
public static readonly DependencyProperty ViewNameProperty =
|
||
DependencyProperty.Register(nameof(ViewName), typeof(string), typeof(TabContentView), new PropertyMetadata(null, OnRegionOrViewNameChanged));
|
||
|
||
public string ViewName
|
||
{
|
||
get => (string)GetValue(ViewNameProperty);
|
||
set => SetValue(ViewNameProperty, value);
|
||
}
|
||
#endregion
|
||
|
||
private void TabContentView_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(RegionName))
|
||
return;
|
||
|
||
_regionManager = ContainerLocator.Current.Resolve<IRegionManager>();
|
||
|
||
// 确保 region/manager 设置在后续导航前准备好(但不要重复注册 region 这里)
|
||
// We will call PrepareRegionForRegistration inside EnsureNavigateIfNeeded before actual registration.
|
||
EnsureNavigateIfNeeded();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"TabContentView_Loaded 出错: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void TabContentView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||
=> EnsureNavigateIfNeeded();
|
||
|
||
private void TabContentView_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||
=> EnsureNavigateIfNeeded();
|
||
|
||
private void EnsureNavigateIfNeeded()
|
||
{
|
||
try
|
||
{
|
||
if (_navigated)
|
||
return;
|
||
|
||
if (string.IsNullOrWhiteSpace(RegionName) || string.IsNullOrWhiteSpace(ViewName))
|
||
return;
|
||
|
||
if (!IsLoaded || !IsVisible)
|
||
return;
|
||
|
||
if (_regionManager == null)
|
||
_regionManager = ContainerLocator.Current.Resolve<IRegionManager>();
|
||
|
||
// 在注册 region 之前准备 host(清理旧 region 与清空 Content),避免 Prism 抛 Content 非空异常
|
||
PrepareRegionForRegistration();
|
||
|
||
// 取消之前挂起的导航(保证最后一次胜出)
|
||
if (_pendingNavigationOp != null && _pendingNavigationOp.Status == DispatcherOperationStatus.Pending)
|
||
{
|
||
Debug.WriteLine($"取消挂起导航: region={RegionName}, view={ViewName}");
|
||
_pendingNavigationOp.Abort();
|
||
_pendingNavigationOp = null;
|
||
}
|
||
|
||
var desiredView = ViewName;
|
||
var desiredRegion = RegionName;
|
||
|
||
_pendingNavigationOp = Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
try
|
||
{
|
||
if (_regionManager == null)
|
||
_regionManager = ContainerLocator.Current.Resolve<IRegionManager>();
|
||
|
||
// 现在把 PART_ContentHost 注册为一个 region(设置 RegionName/RegionManager)
|
||
// 注意:如果前面清理正确,这里不会再触发 ContentControl already has content 错误
|
||
RegionManager.SetRegionName(PART_ContentHost, desiredRegion);
|
||
RegionManager.SetRegionManager(PART_ContentHost, _regionManager);
|
||
|
||
Debug.WriteLine($"开始 RequestNavigate -> region={desiredRegion}, view={desiredView}");
|
||
|
||
_regionManager.RequestNavigate(desiredRegion, desiredView, result =>
|
||
{
|
||
try
|
||
{
|
||
if (result.Success == true)
|
||
{
|
||
_navigated = true;
|
||
Debug.WriteLine($"导航成功: region={desiredRegion}, view={desiredView}");
|
||
}
|
||
else
|
||
{
|
||
_navigated = false;
|
||
Debug.WriteLine($"导航失败: region={desiredRegion}, view={desiredView}, error={result.Exception?.Message}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_navigated = false;
|
||
Debug.WriteLine($"导航回调异常: {ex.Message}");
|
||
}
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"调度导航异常: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
_pendingNavigationOp = null;
|
||
}
|
||
}), DispatcherPriority.Background);
|
||
|
||
Debug.WriteLine($"调度导航: Region={RegionName}, View={ViewName}, Loaded={IsLoaded}, Visible={IsVisible}, navigated={_navigated}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"EnsureNavigateIfNeeded 异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在注册 region 之前清理宿主控件与 RegionManager 中可能残留的 region。
|
||
/// 这一步是防止 Prism 在 adapt 时因为 ContentControl.Content 非空而抛异常。
|
||
/// </summary>
|
||
private void PrepareRegionForRegistration()
|
||
{
|
||
try
|
||
{
|
||
// 如果 RegionManager 中已存在同名 region,则先移除它(并 RemoveAll 内容)
|
||
if (_regionManager != null && _regionManager.Regions.ContainsRegionWithName(RegionName))
|
||
{
|
||
try
|
||
{
|
||
var existing = _regionManager.Regions[RegionName];
|
||
existing.RemoveAll();
|
||
_regionManager.Regions.Remove(RegionName);
|
||
Debug.WriteLine($"已移除旧 region: {RegionName}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"移除旧 region 发生异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// 如果宿主 ContentControl 已经有内容,清空它(很关键)
|
||
if (PART_ContentHost != null && PART_ContentHost.Content != null)
|
||
{
|
||
Debug.WriteLine($"清空 PART_ContentHost.Content (原内容类型: {PART_ContentHost.Content.GetType().Name})");
|
||
PART_ContentHost.Content = null;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"PrepareRegionForRegistration 异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void TabContentView_Unloaded(object sender, RoutedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
// 取消挂起导航
|
||
if (_pendingNavigationOp != null && _pendingNavigationOp.Status == DispatcherOperationStatus.Pending)
|
||
{
|
||
_pendingNavigationOp.Abort();
|
||
_pendingNavigationOp = null;
|
||
}
|
||
|
||
// 清理 region 与宿主内容
|
||
if (!string.IsNullOrWhiteSpace(RegionName))
|
||
{
|
||
var rm = _regionManager ?? ContainerLocator.Current.Resolve<IRegionManager>();
|
||
try
|
||
{
|
||
if (rm != null && rm.Regions.ContainsRegionWithName(RegionName))
|
||
{
|
||
var region = rm.Regions[RegionName];
|
||
region.RemoveAll();
|
||
rm.Regions.Remove(RegionName);
|
||
Debug.WriteLine($"卸载并移除 region: {RegionName}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"TabContentView_Unloaded 清理 region 异常: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
if (PART_ContentHost != null && PART_ContentHost.Content != null)
|
||
{
|
||
PART_ContentHost.Content = null;
|
||
Debug.WriteLine($"Unloaded: 清空 PART_ContentHost.Content");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"TabContentView_Unloaded 清理异常: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
_navigated = false;
|
||
}
|
||
}
|
||
|
||
private static void OnRegionOrViewNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||
{
|
||
if (d is TabContentView tc)
|
||
{
|
||
// 新参数到来,允许再次导航
|
||
tc._navigated = false;
|
||
|
||
// 取消旧挂起导航
|
||
if (tc._pendingNavigationOp != null && tc._pendingNavigationOp.Status == DispatcherOperationStatus.Pending)
|
||
{
|
||
tc._pendingNavigationOp.Abort();
|
||
tc._pendingNavigationOp = null;
|
||
}
|
||
|
||
// 尝试导航(这一调用会在 Loaded/可见时真正执行)
|
||
tc.EnsureNavigateIfNeeded();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|