From eeecef4db95df5014634d95ccf93c7e443468a7e Mon Sep 17 00:00:00 2001 From: DHR60 Date: Sat, 18 Apr 2026 11:18:17 +0000 Subject: [PATCH] Fix (#9143) * Adjust XHTTP style * Add xray tun custom support --- v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 11 ++++- v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx | 5 ++- v2rayN/ServiceLib/Resx/ResUI.fr.resx | 7 +++- v2rayN/ServiceLib/Resx/ResUI.hu.resx | 5 ++- v2rayN/ServiceLib/Resx/ResUI.resx | 5 ++- v2rayN/ServiceLib/Resx/ResUI.ru.resx | 5 ++- v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 5 ++- v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 5 ++- .../V2ray/V2rayConfigTemplateService.cs | 10 ++++- .../CoreConfig/V2ray/V2rayDnsService.cs | 10 ++--- .../ViewModels/DNSSettingViewModel.cs | 19 +++++++++ .../ViewModels/FullConfigTemplateViewModel.cs | 30 ++++++++++---- .../Views/AddServerWindow.axaml | 16 ++++---- .../Views/DNSSettingWindow.axaml | 27 ++++++++---- .../Views/DNSSettingWindow.axaml.cs | 1 + .../Views/FullConfigTemplateWindow.axaml | 27 ++++++++---- .../Views/FullConfigTemplateWindow.axaml.cs | 3 +- v2rayN/v2rayN/Views/AddServerWindow.xaml | 6 ++- v2rayN/v2rayN/Views/DNSSettingWindow.xaml | 41 ++++++++++++++----- v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs | 1 + .../Views/FullConfigTemplateWindow.xaml | 41 ++++++++++++++----- .../Views/FullConfigTemplateWindow.xaml.cs | 1 + 22 files changed, 211 insertions(+), 70 deletions(-) diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 234cdef3..0743b6c7 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -4681,7 +4681,16 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 XHTTP Extra raw JSON, format: { XHTTP Object } 的本地化字符串。 + /// 查找类似 XHTTP Extra 的本地化字符串。 + /// + public static string TransportExtra { + get { + return ResourceManager.GetString("TransportExtra", resourceCulture); + } + } + + /// + /// 查找类似 Raw JSON, format: { XHTTP Object } 的本地化字符串。 /// public static string TransportExtraTip { get { diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 08aaf893..84f9722e 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1321,7 +1321,7 @@ حالت xhttp - جیسون خام XHTTP Extra, فرمت: { XHTTPObject } + Raw JSON, format: { XHTTP Object } هنگام بستن پنجره در سینی پنهان شوید @@ -1704,4 +1704,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Host + + XHTTP Extra + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index 8540727f..84033130 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -1327,7 +1327,7 @@ Mode XHTTP - JSON brut XHTTP Extra, format : { XHTTPObject } + Raw JSON, format: { XHTTP Object } Masquer dans la barre d’état à la fermeture de la fenêtre @@ -1707,4 +1707,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Host - + + XHTTP Extra + + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index f761cca9..e58ae6f0 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1321,7 +1321,7 @@ xhttp mód - XHTTP Extra nyers JSON, formátum: { XHTTP Objektum } + Raw JSON, format: { XHTTP Object } Ablak bezárásakor a tálcára rejtés @@ -1704,4 +1704,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Host + + XHTTP Extra + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index d30c3f31..b4120d3c 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1330,7 +1330,7 @@ xhttp mode - XHTTP Extra raw JSON, format: { XHTTP Object } + Raw JSON, format: { XHTTP Object } Hide to tray when closing the window @@ -1710,4 +1710,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Host + + XHTTP Extra + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 1521e67c..4d30949c 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1321,7 +1321,7 @@ XHTTP-режим - Дополнительный сырой JSON для XHTTP, формат: { XHTTP Object } + Raw JSON, format: { XHTTP Object } Сворачивать в трей при закрытии окна @@ -1704,4 +1704,7 @@ Host + + XHTTP Extra + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 379fb4ba..b47b832e 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1327,7 +1327,7 @@ XHTTP 模式 - XHTTP Extra 原始 JSON,格式: { XHTTPObject } + 原始 JSON,格式: { XHTTPObject } 关闭窗口时隐藏至托盘 @@ -1707,4 +1707,7 @@ Host + + XHTTP Extra + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index a903d168..7ba89b33 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1318,7 +1318,7 @@ xhttp 模式 - XHTTP Extra 原始 JSON,格式: { XHTTPObject } + 原始 JSON,格式: { XHTTPObject } 關閉視窗時隱藏至托盤 @@ -1701,4 +1701,7 @@ Host + + XHTTP Extra + \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs index 6e563f0f..e6bc48cb 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs @@ -5,12 +5,18 @@ public partial class CoreConfigV2rayService private string ApplyFullConfigTemplate() { var fullConfigTemplate = context.FullConfigTemplate; - if (fullConfigTemplate == null || !fullConfigTemplate.Enabled || fullConfigTemplate.Config.IsNullOrEmpty()) + if (fullConfigTemplate is not { Enabled: true }) { return JsonUtils.Serialize(_coreConfig); } - var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplate.Config); + var fullConfigTemplateItem = context.IsTunEnabled ? fullConfigTemplate.TunConfig : fullConfigTemplate.Config; + if (fullConfigTemplateItem.IsNullOrEmpty()) + { + return JsonUtils.Serialize(_coreConfig); + } + + var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplateItem); if (fullConfigTemplateNode == null) { return JsonUtils.Serialize(_coreConfig); diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs index 6b0d335d..7faae5b1 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs @@ -370,11 +370,11 @@ public partial class CoreConfigV2rayService try { var item = context.RawDnsItem; - var normalDNS = item?.NormalDNS; + var customDNS = context.IsTunEnabled ? item?.TunDNS : item?.NormalDNS; var domainStrategy4Freedom = item?.DomainStrategy4Freedom; - if (normalDNS.IsNullOrEmpty()) + if (customDNS.IsNullOrEmpty()) { - normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); + customDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); } //Outbound Freedom domainStrategy @@ -389,11 +389,11 @@ public partial class CoreConfigV2rayService } } - var obj = JsonUtils.ParseJson(normalDNS); + var obj = JsonUtils.ParseJson(customDNS); if (obj is null) { List servers = []; - var arrDNS = normalDNS.Split(','); + var arrDNS = customDNS.Split(','); foreach (var str in arrDNS) { servers.Add(str); diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs index 00178d17..25fbe4b9 100644 --- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs @@ -20,6 +20,7 @@ public class DNSSettingViewModel : MyReactiveObject [Reactive] public string DomainStrategy4FreedomCompatible { get; set; } [Reactive] public string DomainDNSAddressCompatible { get; set; } [Reactive] public string NormalDNSCompatible { get; set; } + [Reactive] public string TunDNSCompatible { get; set; } [Reactive] public string DomainStrategy4Freedom2Compatible { get; set; } [Reactive] public string DomainDNSAddress2Compatible { get; set; } @@ -43,6 +44,7 @@ public class DNSSettingViewModel : MyReactiveObject ImportDefConfig4V2rayCompatibleCmd = ReactiveCommand.CreateFromTask(async () => { NormalDNSCompatible = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); + TunDNSCompatible = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); await Task.CompletedTask; }); @@ -84,6 +86,7 @@ public class DNSSettingViewModel : MyReactiveObject DomainStrategy4FreedomCompatible = item1?.DomainStrategy4Freedom ?? string.Empty; DomainDNSAddressCompatible = item1?.DomainDNSAddress ?? string.Empty; NormalDNSCompatible = item1?.NormalDNS ?? string.Empty; + TunDNSCompatible = item1?.TunDNS ?? string.Empty; var item2 = await AppManager.Instance.GetDNSItem(ECoreType.sing_box); SBCustomDNSEnableCompatible = item2.Enabled; @@ -124,6 +127,21 @@ public class DNSSettingViewModel : MyReactiveObject } } } + if (TunDNSCompatible.IsNotEmpty()) + { + var obj = JsonUtils.ParseJson(TunDNSCompatible); + if (obj != null && obj["servers"] != null) + { + } + else + { + if (TunDNSCompatible.Contains('{') || TunDNSCompatible.Contains('}')) + { + NoticeManager.Instance.Enqueue(ResUI.FillCorrectDNSText); + return; + } + } + } if (NormalDNS2Compatible.IsNotEmpty()) { var obj2 = JsonUtils.Deserialize(NormalDNS2Compatible); @@ -149,6 +167,7 @@ public class DNSSettingViewModel : MyReactiveObject item1.DomainDNSAddress = DomainDNSAddressCompatible; item1.UseSystemHosts = UseSystemHostsCompatible; item1.NormalDNS = NormalDNSCompatible; + item1.TunDNS = TunDNSCompatible; await ConfigHandler.SaveDNSItems(_config, item1); var item2 = await AppManager.Instance.GetDNSItem(ECoreType.sing_box); diff --git a/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs b/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs index 3a50b52e..78cd10a2 100644 --- a/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs @@ -13,6 +13,9 @@ public class FullConfigTemplateViewModel : MyReactiveObject [Reactive] public string FullConfigTemplate4Ray { get; set; } + [Reactive] + public string FullTunConfigTemplate4Ray { get; set; } + [Reactive] public string FullConfigTemplate4Singbox { get; set; } @@ -50,10 +53,15 @@ public class FullConfigTemplateViewModel : MyReactiveObject private async Task Init() { var item = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.Xray); - EnableFullConfigTemplate4Ray = item?.Enabled ?? false; - FullConfigTemplate4Ray = item?.Config ?? string.Empty; - AddProxyOnly4Ray = item?.AddProxyOnly ?? false; - ProxyDetour4Ray = item?.ProxyDetour ?? string.Empty; + if (item == null) + { + return; + } + EnableFullConfigTemplate4Ray = item.Enabled; + FullConfigTemplate4Ray = item.Config ?? string.Empty; + FullTunConfigTemplate4Ray = item.TunConfig ?? string.Empty; + AddProxyOnly4Ray = item.AddProxyOnly ?? false; + ProxyDetour4Ray = item.ProxyDetour ?? string.Empty; var item2 = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.sing_box); EnableFullConfigTemplate4Singbox = item2?.Enabled ?? false; @@ -82,10 +90,13 @@ public class FullConfigTemplateViewModel : MyReactiveObject private async Task SaveXrayConfigAsync() { var item = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.Xray); + if (item == null) + { + return false; + } item.Enabled = EnableFullConfigTemplate4Ray; - item.Config = null; - item.Config = FullConfigTemplate4Ray; + item.TunConfig = FullTunConfigTemplate4Ray; item.AddProxyOnly = AddProxyOnly4Ray; item.ProxyDetour = ProxyDetour4Ray; @@ -97,10 +108,11 @@ public class FullConfigTemplateViewModel : MyReactiveObject private async Task SaveSingboxConfigAsync() { var item = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.sing_box); + if (item == null) + { + return false; + } item.Enabled = EnableFullConfigTemplate4Singbox; - item.Config = null; - item.TunConfig = null; - item.Config = FullConfigTemplate4Singbox; item.TunConfig = FullTunConfigTemplate4Singbox; diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml index 1d2bb899..56a579db 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml @@ -814,17 +814,17 @@ Grid.Column="0" Margin="{StaticResource Margin4}" VerticalAlignment="Top" - Text="{x:Static resx:ResUI.TransportExtraTip}" + Text="{x:Static resx:ResUI.TransportExtra}" TextWrapping="Wrap" /> - + IsExpanded="True"> + + + + + - - - + + + + + + + + + + + + diff --git a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs index dd39e229..e2ea1201 100644 --- a/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs @@ -52,6 +52,7 @@ public partial class DNSSettingWindow : WindowBase this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.TunDNSCompatible, v => v.txttunDNSCompatible.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables); diff --git a/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml b/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml index 1a2b482c..7ff49937 100644 --- a/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml @@ -90,13 +90,26 @@ - - - + + + + + + + + + + + + diff --git a/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml.cs index bfe0c2c5..6ea6e994 100644 --- a/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml.cs @@ -12,13 +12,14 @@ public partial class FullConfigTemplateWindow : WindowBase Close(); + btnCancel.Click += (_, _) => Close(); ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler); this.WhenActivated(disposables => { this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Ray, v => v.rayFullTunConfigTemplate.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml b/v2rayN/v2rayN/Views/AddServerWindow.xaml index 25a1234b..ec86e904 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml @@ -1071,7 +1071,7 @@ Margin="{StaticResource Margin4}" VerticalAlignment="Top" Style="{StaticResource ToolbarTextBlock}" - Text="{x:Static resx:ResUI.TransportExtraTip}" + Text="{x:Static resx:ResUI.TransportExtra}" TextWrapping="Wrap" /> diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml index 8788e97d..d27188a4 100644 --- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml @@ -453,16 +453,37 @@ - + + + + + + + + + + + + + diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs index 2710b102..a7f1bd12 100644 --- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs @@ -50,6 +50,7 @@ public partial class DNSSettingWindow this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.TunDNSCompatible, v => v.txttunDNSCompatible.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml b/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml index d3ca8af7..4b9953d7 100644 --- a/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml +++ b/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml @@ -107,16 +107,37 @@ - + + + + + + + + + + + + + diff --git a/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs b/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs index a9f95a53..031dc40a 100644 --- a/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs @@ -17,6 +17,7 @@ public partial class FullConfigTemplateWindow { this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Ray, v => v.rayFullTunConfigTemplate.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);