From e2f429232165b1396c48a588b2a7ba14686521f6 Mon Sep 17 00:00:00 2001
From: DHR60 <192860629+DHR60@users.noreply.github.com>
Date: Sun, 1 Nov 2026 12:00:02 +0000
Subject: [PATCH] ReactiveUI 26 (#10249)
* ReactiveUI 25
* Fix
* Up
* ReactiveUI 26
---
v2rayN/Directory.Packages.props | 7 ++---
v2rayN/ServiceLib/Common/Extension.cs | 2 +-
v2rayN/ServiceLib/ServiceLib.csproj | 4 ---
.../ViewModels/AddServerViewModel.cs | 11 ++++++--
.../ViewModels/DNSSettingViewModel.cs | 9 ++++--
.../Views/AddServerWindow.axaml.cs | 2 +-
.../Views/DNSSettingWindow.axaml.cs | 12 +++-----
v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj | 4 ---
v2rayN/v2rayN/Base/ViewHost.cs | 5 ++--
v2rayN/v2rayN/Common/SimpleViewLocator.cs | 28 +++++++++++--------
v2rayN/v2rayN/Views/AddServerWindow.xaml.cs | 2 +-
v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs | 14 +++-------
v2rayN/v2rayN/Views/StatusBarView.xaml.cs | 8 +++---
v2rayN/v2rayN/v2rayN.csproj | 4 ---
14 files changed, 52 insertions(+), 60 deletions(-)
diff --git a/v2rayN/Directory.Packages.props b/v2rayN/Directory.Packages.props
index 663b2545..992e02f6 100644
--- a/v2rayN/Directory.Packages.props
+++ b/v2rayN/Directory.Packages.props
@@ -11,15 +11,14 @@
-
+
-
-
-
+
+
diff --git a/v2rayN/ServiceLib/Common/Extension.cs b/v2rayN/ServiceLib/Common/Extension.cs
index f9ccdc58..bf2f3d96 100644
--- a/v2rayN/ServiceLib/Common/Extension.cs
+++ b/v2rayN/ServiceLib/Common/Extension.cs
@@ -143,7 +143,7 @@ public static class Extension
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0)
{
- return Signal.Defer(() => interaction.Handle(input))
+ return Signal.Defer(() => interaction.WhenHandled(input))
.Catch>(ex =>
{
Logging.SaveLog($"Unhandled interaction exception in {memberName} at {filePath}:{lineNumber}", ex);
diff --git a/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayN/ServiceLib/ServiceLib.csproj
index 69729807..b66c9eec 100644
--- a/v2rayN/ServiceLib/ServiceLib.csproj
+++ b/v2rayN/ServiceLib/ServiceLib.csproj
@@ -10,10 +10,6 @@
true
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
diff --git a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs
index fb89f4fe..aea7ce68 100644
--- a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs
@@ -103,6 +103,9 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
[Reactive]
public partial string MasqueHeaders { get; set; }
+ [Reactive]
+ public partial string Network { get; set; }
+
[Reactive]
public partial string RawHeaderType { get; set; }
@@ -274,7 +277,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
this.WhenAnyValue(x => x.CertSha)
.Subscribe(_ => UpdateCertTip());
- this.WhenAnyValue(x => x.SelectedSource.Network)
+ this.WhenAnyValue(x => x.Network)
.Subscribe(_ =>
{
this.RaisePropertyChanged(nameof(TransportHeaderType));
@@ -299,6 +302,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
CoreType = SelectedSource?.CoreType?.ToString();
AllowInsecure = SelectedSource?.GetAllowInsecure() == true;
MuxEnabled = SelectedSource?.MuxEnabled == true;
+ Network = SelectedSource?.Network ?? Global.DefaultNetwork;
Cert = SelectedSource?.Cert ?? string.Empty;
CertSha = SelectedSource?.CertSha ?? string.Empty;
@@ -405,10 +409,11 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
SelectedSource.MuxEnabled = MuxEnabled;
SelectedSource.Cert = Cert.IsNullOrEmpty() ? string.Empty : Cert;
SelectedSource.CertSha = CertSha.IsNullOrEmpty() ? string.Empty : CertSha;
- if (!Global.Networks.Contains(SelectedSource.Network))
+ if (!Global.Networks.Contains(Network))
{
- SelectedSource.Network = Global.DefaultNetwork;
+ Network = Global.DefaultNetwork;
}
+ SelectedSource.Network = Network;
var transport = new TransportExtraItem
{
diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs
index a02bf152..c1314749 100644
--- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs
@@ -35,7 +35,7 @@ public partial class DNSSettingViewModel : MyReactiveObject, ICloseable
[Reactive] public partial bool RayCustomDNSEnableCompatible { get; set; }
[Reactive] public partial bool SBCustomDNSEnableCompatible { get; set; }
- public bool IsSimpleDNSEnabled => !(RayCustomDNSEnableCompatible && SBCustomDNSEnableCompatible);
+ [ObservableAsProperty] public partial bool IsSimpleDNSEnabled { get; }
public ReactiveCommand SaveCmd { get; }
public ReactiveCommand ImportDefConfig4V2rayCompatibleCmd { get; }
@@ -60,8 +60,11 @@ public partial class DNSSettingViewModel : MyReactiveObject, ICloseable
await Task.CompletedTask;
});
- this.WhenAnyValue(x => x.RayCustomDNSEnableCompatible, x => x.SBCustomDNSEnableCompatible)
- .Subscribe(_ => this.RaisePropertyChanged(nameof(IsSimpleDNSEnabled)));
+ _isSimpleDNSEnabledHelper = this.WhenAnyValue(
+ x => x.RayCustomDNSEnableCompatible,
+ x => x.SBCustomDNSEnableCompatible,
+ (a, b) => !(a && b))
+ .ToProperty(this, nameof(IsSimpleDNSEnabled));
_ = Init();
}
diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs
index d7805232..ae9183ab 100644
--- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs
+++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs
@@ -152,7 +152,7 @@ public partial class AddServerWindow : WindowBase
})
.DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RawHeaderType, v => v.cmbHeaderTypeRaw.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Host, v => v.txtRequestHostRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Path, v => v.txtPathRaw.Text).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs
index 2ab1a608..866ed941 100644
--- a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs
+++ b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs
@@ -67,14 +67,10 @@ public partial class DNSSettingWindow : WindowBase
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables);
- this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)
- .Select(b => !b)
- .BindTo(txtBasicDNSSettingsInvalid, t => t.IsVisible);
- this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)
- .Select(b => !b)
- .BindTo(txtAdvancedDNSSettingsInvalid, t => t.IsVisible);
- this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridBasicDNSSettings.IsEnabled).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridAdvancedDNSSettings.IsEnabled).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.txtBasicDNSSettingsInvalid.IsVisible, isSimpleDnsEnabled => !isSimpleDnsEnabled).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.txtAdvancedDNSSettingsInvalid.IsVisible, isSimpleDnsEnabled => !isSimpleDnsEnabled).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridBasicDNSSettings.IsEnabled).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridAdvancedDNSSettings.IsEnabled).DisposeWith(disposables);
});
}
diff --git a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj
index 28630574..4b631e4f 100644
--- a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj
+++ b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj
@@ -23,10 +23,6 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
diff --git a/v2rayN/v2rayN/Base/ViewHost.cs b/v2rayN/v2rayN/Base/ViewHost.cs
index e6d5b068..ce563fce 100644
--- a/v2rayN/v2rayN/Base/ViewHost.cs
+++ b/v2rayN/v2rayN/Base/ViewHost.cs
@@ -4,9 +4,10 @@ namespace v2rayN.Base;
public static class ViewHost
{
- public static void Show(
+ public static void Show(
ContentControl host,
- object? viewModel)
+ TViewModel? viewModel)
+ where TViewModel : class
{
if (viewModel == null)
{
diff --git a/v2rayN/v2rayN/Common/SimpleViewLocator.cs b/v2rayN/v2rayN/Common/SimpleViewLocator.cs
index b3395fda..8b57bfbf 100644
--- a/v2rayN/v2rayN/Common/SimpleViewLocator.cs
+++ b/v2rayN/v2rayN/Common/SimpleViewLocator.cs
@@ -37,31 +37,27 @@ public class SimpleViewLocator : IViewLocator
public static SimpleViewLocator Instance => _instance.Value;
public IViewFor? ResolveView() where TViewModel : class
- {
- return ResolveView(null);
- }
-
- public IViewFor? ResolveView(string? contract) where TViewModel : class
{
if (_mappings.TryGetValue(typeof(TViewModel), out var factory))
{
- return factory() as IViewFor;
+ var view = factory() as IViewFor;
+ return view;
}
return null;
}
- public IViewFor? ResolveView(object? instance)
+ public IViewFor? ResolveView(TViewModel viewModel, string? contract) where TViewModel : class
{
- return ResolveView(instance, null);
+ return ResolveView();
}
- public IViewFor? ResolveView(object? instance, string? contract)
+ public IViewFor? ResolveView(object? viewModel, string? contract)
{
- if (instance == null)
+ if (viewModel == null)
{
return null;
}
- var viewModelType = instance.GetType();
+ var viewModelType = viewModel.GetType();
if (_mappings.TryGetValue(viewModelType, out var factory))
{
return factory();
@@ -69,6 +65,16 @@ public class SimpleViewLocator : IViewLocator
return null;
}
+ public IViewFor? ResolveViewUnsafe(object? viewModel, string? contract)
+ {
+ return ResolveView(viewModel, contract);
+ }
+
+ public IViewFor? ResolveView(TViewModel instance) where TViewModel : class
+ {
+ return ResolveView(instance, null);
+ }
+
public void Register(Func factory)
where TViewModel : class
where TView : class, IViewFor
diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs
index f8e1573f..7effbc40 100644
--- a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs
@@ -150,7 +150,7 @@ public partial class AddServerWindow
})
.DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RawHeaderType, v => v.cmbHeaderTypeRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Host, v => v.txtRequestHostRaw.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Path, v => v.txtPathRaw.Text).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs
index dcf267fe..3260ce89 100644
--- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs
@@ -63,16 +63,10 @@ public partial class DNSSettingWindow
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables);
- this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)
- .Select(b => b ? Visibility.Collapsed : Visibility.Visible)
- .BindTo(this, x => x.txtBasicDNSSettingsInvalid.Visibility)
- .DisposeWith(disposables);
- this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)
- .Select(b => b ? Visibility.Collapsed : Visibility.Visible)
- .BindTo(this, x => x.txtAdvancedDNSSettingsInvalid.Visibility)
- .DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridBasicDNSSettings.IsEnabled).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridAdvancedDNSSettings.IsEnabled).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.txtBasicDNSSettingsInvalid.Visibility, isSimpleDnsEnabled => isSimpleDnsEnabled ? Visibility.Collapsed : Visibility.Visible).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.txtAdvancedDNSSettingsInvalid.Visibility, isSimpleDnsEnabled => isSimpleDnsEnabled ? Visibility.Collapsed : Visibility.Visible).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridBasicDNSSettings.IsEnabled).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridAdvancedDNSSettings.IsEnabled).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
}
diff --git a/v2rayN/v2rayN/Views/StatusBarView.xaml.cs b/v2rayN/v2rayN/Views/StatusBarView.xaml.cs
index 4dab2d75..aeadc0c9 100644
--- a/v2rayN/v2rayN/Views/StatusBarView.xaml.cs
+++ b/v2rayN/v2rayN/Views/StatusBarView.xaml.cs
@@ -18,10 +18,10 @@ public partial class StatusBarView
this.WhenActivated(disposables =>
{
//system proxy
- this.OneWayBind(ViewModel, vm => vm.BlSystemProxyClear, v => v.menuSystemProxyClear2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
- this.OneWayBind(ViewModel, vm => vm.BlSystemProxySet, v => v.menuSystemProxySet2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
- this.OneWayBind(ViewModel, vm => vm.BlSystemProxyNothing, v => v.menuSystemProxyNothing2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
- this.OneWayBind(ViewModel, vm => vm.BlSystemProxyPac, v => v.menuSystemProxyPac2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.BlSystemProxyClear, v => v.menuSystemProxyClear2.Visibility, conversionHint: BooleanToVisibilityHints.UseHidden, converter: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.BlSystemProxySet, v => v.menuSystemProxySet2.Visibility, conversionHint: BooleanToVisibilityHints.UseHidden, converter: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.BlSystemProxyNothing, v => v.menuSystemProxyNothing2.Visibility, conversionHint: BooleanToVisibilityHints.UseHidden, converter: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
+ this.OneWayBind(ViewModel, vm => vm.BlSystemProxyPac, v => v.menuSystemProxyPac2.Visibility, conversionHint: BooleanToVisibilityHints.UseHidden, converter: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SystemProxyClearCmd, v => v.menuSystemProxyClear).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SystemProxySetCmd, v => v.menuSystemProxySet).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SystemProxyNothingCmd, v => v.menuSystemProxyNothing).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN/v2rayN.csproj b/v2rayN/v2rayN/v2rayN.csproj
index 237a1271..880548d3 100644
--- a/v2rayN/v2rayN/v2rayN.csproj
+++ b/v2rayN/v2rayN/v2rayN.csproj
@@ -16,10 +16,6 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-