136 lines
4.4 KiB
C#
136 lines
4.4 KiB
C#
using Prism.Commands;
|
||
using Prism.Ioc;
|
||
using System;
|
||
using System.Collections.ObjectModel;
|
||
using System.Windows.Input;
|
||
using UIShare.PubEvent;
|
||
using UIShare.UIViewModel;
|
||
using UIShare.ViewModelBase;
|
||
|
||
namespace DeviceEditModule.ViewModels
|
||
{
|
||
/// <summary>
|
||
/// 弹窗管理器 ViewModel。
|
||
/// <para>
|
||
/// 职责:<br/>
|
||
/// 1. 订阅 <see cref="AddDialogTabEvent"/>,将外部弹窗注册为 Tab;<br/>
|
||
/// 2. 维护 <see cref="TagItems"/> 集合,控制选中/关闭逻辑;<br/>
|
||
/// 3. 最小化:通过 <see cref="MinimizeRequested"/> 事件通知 View 执行 P/Invoke 窗口操作;<br/>
|
||
/// 4. 关闭:调用 <see cref="RequestClose"/>。
|
||
/// </para>
|
||
/// </summary>
|
||
public class DialogMangerViewModel : DialogViewModelBase, IDisposable
|
||
{
|
||
#region 属性
|
||
|
||
/// <summary>所有 Tab 项集合,绑定到标签条的 ItemsControl。</summary>
|
||
public ObservableCollection<DialogTabItemVM> TagItems { get; } = new();
|
||
|
||
private DialogTabItemVM? _selectedTag;
|
||
/// <summary>当前激活的 Tab,其 Content 显示在内容区。</summary>
|
||
public DialogTabItemVM? SelectedTag
|
||
{
|
||
get => _selectedTag;
|
||
set => SetProperty(ref _selectedTag, value);
|
||
}
|
||
|
||
/// <summary>是否没有任何 Tab(用于绑定空状态提示的 Visibility)。</summary>
|
||
public bool HasNoTabs => TagItems.Count == 0;
|
||
|
||
#endregion
|
||
|
||
#region 命令
|
||
|
||
public ICommand MinimizeCommand { get; }
|
||
public ICommand CloseCommand { get; }
|
||
|
||
#endregion
|
||
|
||
#region 事件
|
||
|
||
/// <summary>
|
||
/// View 订阅此事件后,在事件回调里执行 P/Invoke 最小化。
|
||
/// 这样 ViewModel 无需引用任何 UI 或 Win32 类型。
|
||
/// </summary>
|
||
public event EventHandler? MinimizeRequested;
|
||
public event EventHandler? RestoreRequested;
|
||
#endregion
|
||
|
||
public DialogMangerViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||
{
|
||
MinimizeCommand = new DelegateCommand(OnMinimize);
|
||
CloseCommand = new DelegateCommand(OnClose);
|
||
|
||
// 订阅来自其他模块的"添加 Tab"事件
|
||
_eventAggregator.GetEvent<AddDialogTabEvent>().Subscribe(OnAddTab, ThreadOption.UIThread);
|
||
_eventAggregator.GetEvent<CancelMinimizeEvent>().Subscribe(()=>RestoreRequested.Invoke(this, EventArgs.Empty));
|
||
}
|
||
|
||
#region 命令处理
|
||
|
||
private void OnMinimize() => MinimizeRequested?.Invoke(this, EventArgs.Empty);
|
||
|
||
private void OnClose()
|
||
{
|
||
// 关闭前清空所有 Tab,释放内容引用
|
||
TagItems.Clear();
|
||
SelectedTag = null;
|
||
RequestClose.Invoke();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Tab 管理
|
||
|
||
/// <summary>收到事件:创建 Tab 并追加到集合,自动切换选中。</summary>
|
||
private void OnAddTab(DialogTabInfo info)
|
||
{
|
||
var tab = new DialogTabItemVM(OnSelectTab, OnCloseTab)
|
||
{
|
||
Title = info.Title,
|
||
Content = info.Content
|
||
};
|
||
|
||
TagItems.Add(tab);
|
||
RaisePropertyChanged(nameof(HasNoTabs));
|
||
ActivateTab(tab);
|
||
}
|
||
|
||
/// <summary>激活(选中)指定 Tab,其余全部取消选中。</summary>
|
||
private void OnSelectTab(DialogTabItemVM tab) => ActivateTab(tab);
|
||
|
||
/// <summary>关闭指定 Tab,自动选中相邻 Tab(或清空内容区)。</summary>
|
||
private void OnCloseTab(DialogTabItemVM tab)
|
||
{
|
||
int idx = TagItems.IndexOf(tab);
|
||
TagItems.Remove(tab);
|
||
RaisePropertyChanged(nameof(HasNoTabs));
|
||
|
||
if (TagItems.Count == 0)
|
||
{
|
||
SelectedTag = null;
|
||
return;
|
||
}
|
||
|
||
// 优先选左侧邻 Tab,无左侧则选当前索引(已向左移一位)
|
||
ActivateTab(TagItems[Math.Max(0, idx - 1)]);
|
||
}
|
||
|
||
private void ActivateTab(DialogTabItemVM tab)
|
||
{
|
||
foreach (var t in TagItems)
|
||
t.IsSelected = false;
|
||
|
||
tab.IsSelected = true;
|
||
SelectedTag = tab;
|
||
}
|
||
|
||
#endregion
|
||
|
||
public void Dispose()
|
||
{
|
||
_eventAggregator.GetEvent<AddDialogTabEvent>().Unsubscribe(OnAddTab);
|
||
}
|
||
}
|
||
}
|