Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
2407cae
docs: define navigation rebuild design
Junevy Jul 11, 2026
e161c11
docs: add navigation rebuild implementation plan
Junevy Jul 11, 2026
1eb12bf
test: add dual-target WPF test harness
Junevy Jul 11, 2026
8c36397
test: harden WPF test harness
Junevy Jul 11, 2026
129828a
feat: add region manager
Junevy Jul 11, 2026
498f3ea
fix: harden region manager
Junevy Jul 11, 2026
a842a2e
feat: add Region attached registration
Junevy Jul 11, 2026
f7ba46b
fix: harden Region lifecycle
Junevy Jul 11, 2026
49224a0
feat: add explicit navigation routes
Junevy Jul 11, 2026
dc1961a
test: strengthen navigation registration coverage
Junevy Jul 11, 2026
b955380
test: cover navigation route lookup
Junevy Jul 11, 2026
7a81e6d
feat: rebuild page navigation around regions
Junevy Jul 11, 2026
446e754
feat: add content navigation service
Junevy Jul 11, 2026
0a81c2f
fix: generalize content host adapter
Junevy Jul 11, 2026
8df8be4
docs: document rebuilt navigation APIs
Junevy Jul 11, 2026
e13cc2c
docs: complete navigation registration examples
Junevy Jul 11, 2026
e1afb62
docs: clarify dialog and DI lifetime limits
Junevy Jul 11, 2026
faa4837
fix: improve content host diagnostics
Junevy Jul 11, 2026
48da100
docs: include region manager lifetime
Junevy Jul 11, 2026
537b0af
添加注释
Junevy Jul 12, 2026
54da2c0
Add: IViewInitialize interface
Junevy Jul 13, 2026
4cb73bc
docs: design dialog service rebuild
Junevy Jul 16, 2026
ed8fde9
docs: plan dialog service rebuild
Junevy Jul 16, 2026
8971c14
feat: add dialog window registration routes
Junevy Jul 16, 2026
5803eaf
test: harden dialog registration validation
Junevy Jul 16, 2026
20dc5ec
refactor: manage dialog windows by type
Junevy Jul 16, 2026
e4c212b
fix: harden dialog window lifecycle
Junevy Jul 16, 2026
4637779
fix: avoid dialog resolution lock inversion
Junevy Jul 16, 2026
bd13519
test: harden dialog manager thread cleanup
Junevy Jul 16, 2026
fbcc204
feat: rebuild dialog service around keyed windows
Junevy Jul 16, 2026
6141d6d
fix: harden dialog service lifecycle
Junevy Jul 16, 2026
aaeef45
fix: guard dialog presentation reentrancy
Junevy Jul 16, 2026
74a6897
docs: document keyed dialog service
Junevy Jul 16, 2026
2f5aea4
docs: correct dialog provider lifetime guidance
Junevy Jul 16, 2026
ec75e82
docs: clarify navigation view lifetimes
Junevy Jul 16, 2026
ec2ab69
fix: make dialog callback transactions exception safe
Junevy Jul 16, 2026
7b757fc
fix: complete dialog callback cleanup transactions
Junevy Jul 16, 2026
bd4d2f0
fix: guard dialog subscription cleanup reentrancy
Junevy Jul 16, 2026
973dac7
Feat: Add Singleton & Transient life circle in Extentsions.
Junevy Jul 16, 2026
d032d12
Add: Region unloaded evnet
Junevy Jul 16, 2026
4ad01d8
Feat: Add TabControl adapter.
Junevy Jul 17, 2026
01d4346
Fix: Fix some bugs of TabControl Adapter
Junevy Jul 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Common/Adapters/ContentControlRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using SimpleNavigation.Interface.Adapters;
using System.Windows;
using System.Windows.Controls;

namespace SimpleNavigation.Common.Adapters;

internal sealed class ContentControlRegionAdapter : IContentRegionHostAdapter
{
public RegionHostKind Kind => RegionHostKind.Content;

public bool CanHandle(FrameworkElement region)
=> region is ContentControl && region is not Frame && region is not TabControl;

public void Present(FrameworkElement host, FrameworkElement content)
{
if (host is not ContentControl contentControl || host is Frame)
{
throw new ArgumentException(
$"Host type '{host.GetType().FullName}' must be a non-Frame ContentControl.",
nameof(host));
}

host.Dispatcher.VerifyAccess();
contentControl.Content = content;
}
}
30 changes: 30 additions & 0 deletions Common/Adapters/FrameRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using SimpleNavigation.Interface.Adapters;
using System.Windows;
using System.Windows.Controls;

namespace SimpleNavigation.Common.Adapters;

internal sealed class FrameRegionAdapter : IPageRegionHostAdapter
{
public RegionHostKind Kind => RegionHostKind.Page;

public bool CanHandle(FrameworkElement region) => region is Frame;

public bool Navigate(Frame frame, Page page)
{
frame.Dispatcher.VerifyAccess();
return frame.Navigate(page);
}

public bool CanGoBack(Frame frame)
{
frame.Dispatcher.VerifyAccess();
return frame.CanGoBack;
}

public void GoBack(Frame frame)
{
frame.Dispatcher.VerifyAccess();
frame.GoBack();
}
}
52 changes: 52 additions & 0 deletions Common/Adapters/RegionHostAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using SimpleNavigation.Interface.Adapters;
using System.Windows;

namespace SimpleNavigation.Common.Adapters;

/// <summary>
/// ���������ɽ��ܵ���������
/// </summary>
internal enum RegionHostKind
{
Page,
Content,
}

/// <summary>
/// ��ȡ���䵼��Ԫ�ص� Adapter
/// </summary>
internal static class RegionHostAdapterResolver
{
private static readonly IRegionHostAdapter[] HostAdapters =
{

new FrameRegionAdapter(),
new TabControlRegionAdapter(),
new ContentControlRegionAdapter(),

};

/// <summary>
/// ���� ���Ӷ�������ͣ�ɸѡ��ƥ��� Adapter
/// </summary>
/// <param name="attachedRegion">���Ӷ���</param>
/// <returns>��ƥ��� Adapter <see cref="IRegionHostAdapter"/></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public static IRegionHostAdapter GetRequired(FrameworkElement attachedRegion)
{
if (attachedRegion == null)
throw new ArgumentNullException(nameof(attachedRegion));

foreach (var adapter in HostAdapters)
{
if (adapter.CanHandle(attachedRegion))
return adapter;
}

var regionType = attachedRegion.GetType();
throw new ArgumentException(
$"Region host type '{regionType.FullName}' is not supported.",
nameof(attachedRegion));
}
}
58 changes: 58 additions & 0 deletions Common/Adapters/TabControlRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using SimpleNavigation.Interface.Adapters;
using System.Collections;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace SimpleNavigation.Common.Adapters
{
internal class TabControlRegionAdapter : IContentRegionHostAdapter
{
public RegionHostKind Kind => RegionHostKind.Content;

public bool CanHandle(FrameworkElement region) => region is TabControl;

public void Present(FrameworkElement host, FrameworkElement content)
{
if (host is not TabControl tabControl || content is not UserControl view)
{
throw new ArgumentException(
$"Host type '{host.GetType().FullName}' must be a TabControl.",
nameof(host));
}

host.Dispatcher.VerifyAccess();

if (tabControl.ItemsSource == null)
{
tabControl.Items.Add(content);
}
else
{
if (tabControl.ItemsSource is IList list)
{
//list.Add(new TabItem() { Header = "new tab", Content = view});
if (list.Count <= 0)
throw new ArgumentException("The tab control must be keep at least 1 item");

var targetType = list[0]?.GetType();
object instance = Activator.CreateInstance(targetType);
if (instance != null)
{
FieldInfo contentFi = targetType.GetField("ContentProperty", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
DependencyProperty contentDp = (DependencyProperty)contentFi.GetValue(null);

FieldInfo headerFi = targetType.GetField("HeaderProperty", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
DependencyProperty headerDp = (DependencyProperty)headerFi.GetValue(null);

var header = content.GetType().Name.Replace("View", "");

((DependencyObject)instance).SetValue(headerDp, header);
((DependencyObject)instance).SetValue(contentDp, content);
list.Add(instance);
}
}
}
}
}
}
42 changes: 0 additions & 42 deletions Common/DialogManager.cs

This file was deleted.

Loading