Files
qhmes/yy-admin-master/YY.Admin/Views/Control/TabContentView.xaml.cs

372 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//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 仍然不存在,尝试 RequestNavigatePrism 通常会创建 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();
}
}
}
}