Skip to content

Commit 91bdef0

Browse files
Merge pull request #78 from Fork-Repository-Dedicated/main
feat: 添加导航功能和返回按钮支持,更新语言资源
2 parents 4531bd0 + cdfbe99 commit 91bdef0

File tree

6 files changed

+370
-67
lines changed

6 files changed

+370
-67
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<ResourceDictionary
2+
xmlns="https://github.com/avaloniaui"
3+
xmlns:s="clr-namespace:System;assembly=mscorlib"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
5+
6+
<!-- FormMain -->
7+
<s:String x:Key="LangTitleDownload">Download</s:String>
8+
<s:String x:Key="LangTitleHome">Home</s:String>
9+
<s:String x:Key="LangTitleSetup">Settings</s:String>
10+
<s:String x:Key="LangTitleLink">Multiplayer</s:String>
11+
<s:String x:Key="LangTitleOther">More</s:String>
12+
<s:String x:Key="LangNavigateBack">Back</s:String>
13+
14+
</ResourceDictionary>

PCL.Neo/Assets/Language/zh-CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
<s:String x:Key="LangTitleSetup">设置</s:String>
1010
<s:String x:Key="LangTitleLink">联机</s:String>
1111
<s:String x:Key="LangTitleOther">更多</s:String>
12+
<s:String x:Key="LangNavigateBack">返回</s:String>
1213

1314
</ResourceDictionary>

PCL.Neo/Services/NavigationService.cs

Lines changed: 124 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,43 @@
11
using Microsoft.Extensions.DependencyInjection;
22
using PCL.Neo.ViewModels;
33
using System;
4+
using System.Collections.Generic;
45
using System.Reflection;
56

67
namespace PCL.Neo.Services;
78

9+
public enum NavigationType
10+
{
11+
Forward,
12+
Backward
13+
}
14+
15+
public class NavigationEventArgs : EventArgs
16+
{
17+
public ViewModelBase? OldViewModel { get; }
18+
public ViewModelBase? NewViewModel { get; }
19+
public NavigationType NavigationType { get; }
20+
21+
public NavigationEventArgs(ViewModelBase? oldViewModel, ViewModelBase? newViewModel, NavigationType navigationType)
22+
{
23+
OldViewModel = oldViewModel;
24+
NewViewModel = newViewModel;
25+
NavigationType = navigationType;
26+
}
27+
}
28+
829
public class NavigationService
930
{
1031
public IServiceProvider ServiceProvider { get; init; }
1132

1233
public event Action<ViewModelBase?>? CurrentViewModelChanged;
1334
public event Action<ViewModelBase?>? CurrentSubViewModelChanged;
35+
public event Action<NavigationEventArgs>? Navigating;
36+
37+
// 导航历史记录
38+
private readonly Stack<(Type ViewModelType, Type? SubViewModelType)> _navigationHistory = new();
39+
// 最大历史记录数量
40+
private const int MaxHistoryCount = 30;
1441

1542
private ViewModelBase? _currentViewModel;
1643
public ViewModelBase? CurrentViewModel
@@ -20,6 +47,8 @@ protected set
2047
{
2148
if (value == _currentViewModel)
2249
return;
50+
51+
var oldViewModel = _currentViewModel;
2352
_currentViewModel = value;
2453
CurrentViewModelChanged?.Invoke(value);
2554
}
@@ -33,18 +62,52 @@ protected set
3362
{
3463
if (value == _currentSubViewModel)
3564
return;
65+
66+
var oldSubViewModel = _currentSubViewModel;
3667
_currentSubViewModel = value;
3768
CurrentSubViewModelChanged?.Invoke(value);
3869
}
3970
}
4071

72+
public bool CanGoBack => _navigationHistory.Count > 0;
73+
4174
public NavigationService(IServiceProvider serviceProvider)
4275
{
4376
ServiceProvider = serviceProvider;
4477
}
4578

4679
public virtual T Goto<T>() where T : ViewModelBase
4780
{
81+
var oldViewModel = CurrentViewModel;
82+
var oldSubViewModel = CurrentSubViewModel;
83+
84+
// 保存当前状态到历史记录
85+
if (CurrentViewModel != null)
86+
{
87+
_navigationHistory.Push((CurrentViewModel.GetType(), CurrentSubViewModel?.GetType()));
88+
89+
// 限制历史记录数量
90+
if (_navigationHistory.Count > MaxHistoryCount)
91+
{
92+
var tempStack = new Stack<(Type, Type?)>();
93+
var count = 0;
94+
95+
while (_navigationHistory.Count > 0 && count < MaxHistoryCount)
96+
{
97+
tempStack.Push(_navigationHistory.Pop());
98+
count++;
99+
}
100+
101+
_navigationHistory.Clear();
102+
while (tempStack.Count > 0)
103+
{
104+
_navigationHistory.Push(tempStack.Pop());
105+
}
106+
}
107+
}
108+
109+
T targetVm;
110+
48111
if (typeof(T).GetCustomAttribute<DefaultSubViewModelAttribute>() is { } dsvm)
49112
{
50113
var vm = CurrentViewModel as T;
@@ -55,10 +118,9 @@ public virtual T Goto<T>() where T : ViewModelBase
55118
}
56119
if (CurrentSubViewModel?.GetType() != dsvm.SubViewModel)
57120
CurrentSubViewModel = ServiceProvider.GetRequiredService(dsvm.SubViewModel) as ViewModelBase;
58-
return vm;
121+
targetVm = vm;
59122
}
60-
61-
if (typeof(T).GetCustomAttribute<SubViewModelOfAttribute>() is { } svmo)
123+
else if (typeof(T).GetCustomAttribute<SubViewModelOfAttribute>() is { } svmo)
62124
{
63125
var subVm = CurrentSubViewModel as T;
64126
if (CurrentViewModel?.GetType() != svmo.ParentViewModel)
@@ -68,16 +130,66 @@ public virtual T Goto<T>() where T : ViewModelBase
68130
subVm = ServiceProvider.GetRequiredService<T>();
69131
CurrentSubViewModel = subVm;
70132
}
71-
return subVm;
133+
targetVm = subVm;
72134
}
73-
74-
var targetVm = CurrentViewModel?.GetType() != typeof(T) || CurrentSubViewModel?.GetType() != typeof(T)
75-
? ServiceProvider.GetRequiredService<T>()
76-
: (T)CurrentViewModel;
77-
if (CurrentViewModel?.GetType() != typeof(T))
78-
CurrentViewModel = targetVm;
79-
if (CurrentSubViewModel?.GetType() != typeof(T))
80-
CurrentSubViewModel = targetVm;
135+
else
136+
{
137+
targetVm = CurrentViewModel?.GetType() != typeof(T) || CurrentSubViewModel?.GetType() != typeof(T)
138+
? ServiceProvider.GetRequiredService<T>()
139+
: (T)CurrentViewModel;
140+
if (CurrentViewModel?.GetType() != typeof(T))
141+
CurrentViewModel = targetVm;
142+
if (CurrentSubViewModel?.GetType() != typeof(T))
143+
CurrentSubViewModel = targetVm;
144+
}
145+
146+
// 触发导航事件
147+
Navigating?.Invoke(new NavigationEventArgs(oldViewModel, CurrentViewModel, NavigationType.Forward));
148+
81149
return targetVm;
82150
}
151+
152+
/// <summary>
153+
/// 返回上一个导航状态
154+
/// </summary>
155+
/// <returns>是否成功返回</returns>
156+
public bool GoBack()
157+
{
158+
if (!CanGoBack)
159+
return false;
160+
161+
var oldViewModel = CurrentViewModel;
162+
var oldSubViewModel = CurrentSubViewModel;
163+
164+
var (viewModelType, subViewModelType) = _navigationHistory.Pop();
165+
166+
// 恢复主视图
167+
if (viewModelType != null)
168+
{
169+
CurrentViewModel = ServiceProvider.GetRequiredService(viewModelType) as ViewModelBase;
170+
}
171+
172+
// 恢复子视图
173+
if (subViewModelType != null)
174+
{
175+
CurrentSubViewModel = ServiceProvider.GetRequiredService(subViewModelType) as ViewModelBase;
176+
}
177+
else
178+
{
179+
CurrentSubViewModel = null;
180+
}
181+
182+
// 触发导航事件
183+
Navigating?.Invoke(new NavigationEventArgs(oldViewModel, CurrentViewModel, NavigationType.Backward));
184+
185+
return true;
186+
}
187+
188+
/// <summary>
189+
/// 清空导航历史
190+
/// </summary>
191+
public void ClearHistory()
192+
{
193+
_navigationHistory.Clear();
194+
}
83195
}

PCL.Neo/ViewModels/MainWindowViewModel.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public partial class MainWindowViewModel : ViewModelBase
2525
private ViewModelBase? _currentViewModel;
2626
[ObservableProperty]
2727
private ViewModelBase? _currentSubViewModel;
28+
29+
[ObservableProperty]
30+
private bool _canGoBack;
2831

2932
// 为了设计时的 DataContext
3033
public MainWindowViewModel()
@@ -41,19 +44,29 @@ public MainWindowViewModel(NavigationService navigationService)
4144
this.NavigationService.CurrentViewModelChanged += x =>
4245
{
4346
CurrentViewModel = x;
47+
CanGoBack = NavigationService.CanGoBack;
4448
switch (x)
4549
{
4650
case HomeViewModel:
4751
IsNavBtn1Checked = true;
52+
IsNavBtn2Checked = false;
53+
IsNavBtn3Checked = false;
54+
IsNavBtn4Checked = false;
55+
IsNavBtn5Checked = false;
4856
break;
4957
case DownloadViewModel:
58+
IsNavBtn1Checked = false;
5059
IsNavBtn2Checked = true;
60+
IsNavBtn3Checked = false;
61+
IsNavBtn4Checked = false;
62+
IsNavBtn5Checked = false;
5163
break;
5264
}
5365
};
5466
this.NavigationService.CurrentSubViewModelChanged += x =>
5567
{
5668
CurrentSubViewModel = x;
69+
CanGoBack = NavigationService.CanGoBack;
5770
};
5871
this.NavigationService.Goto<HomeViewModel>();
5972
}
@@ -69,6 +82,16 @@ public void NavigateToDownload()
6982
{
7083
this.NavigationService.Goto<DownloadViewModel>();
7184
}
85+
86+
[RelayCommand]
87+
public void GoBack()
88+
{
89+
if (NavigationService.CanGoBack)
90+
{
91+
NavigationService.GoBack();
92+
CanGoBack = NavigationService.CanGoBack;
93+
}
94+
}
7295

7396
public void Close()
7497
{

0 commit comments

Comments
 (0)