mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-13 20:09:12 +00:00
Compare commits
30 commits
029cb1daf1
...
24a5847acc
Author | SHA1 | Date | |
---|---|---|---|
![]() |
24a5847acc | ||
![]() |
224f9b1c95 | ||
![]() |
25f8730021 | ||
![]() |
6808595fa1 | ||
![]() |
8d61d6caaf | ||
![]() |
7c68e8aece | ||
![]() |
4bf86665b7 | ||
![]() |
ae46b39110 | ||
![]() |
836217266e | ||
![]() |
4e3c2991f9 | ||
![]() |
cdab7a097f | ||
![]() |
1d8b8491ea | ||
![]() |
04dae54654 | ||
![]() |
63bf68376f | ||
![]() |
826f9f833a | ||
![]() |
9317c73084 | ||
![]() |
2d5a5465df | ||
![]() |
af62d9e0f4 | ||
![]() |
2ab044b4fc | ||
![]() |
c76d125ce1 | ||
![]() |
183be53153 | ||
![]() |
52d1eb1e2b | ||
![]() |
521dca33d5 | ||
![]() |
a323484ee3 | ||
![]() |
9a43003c47 | ||
![]() |
e97b98f4bf | ||
![]() |
bd3a733057 | ||
![]() |
0cde086448 | ||
![]() |
8561311a45 | ||
![]() |
57fd56fc05 |
25 changed files with 235 additions and 144 deletions
|
@ -6,10 +6,10 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.3.0" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.7" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.7" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.7" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.7" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.6" />
|
||||
<PackageVersion Include="CliWrap" Version="3.9.0" />
|
||||
<PackageVersion Include="Downloader" Version="4.0.3" />
|
||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.0" />
|
||||
|
@ -19,9 +19,9 @@
|
|||
<PackageVersion Include="ReactiveUI" Version="20.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
<PackageVersion Include="ReactiveUI.WPF" Version="20.4.1" />
|
||||
<PackageVersion Include="Semi.Avalonia" Version="11.3.7" />
|
||||
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.10" />
|
||||
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.1" />
|
||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7" />
|
||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.10" />
|
||||
<PackageVersion Include="NLog" Version="6.0.4" />
|
||||
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||
|
|
|
@ -155,60 +155,61 @@ public class BaseFmt
|
|||
|
||||
protected static int ResolveStdTransport(NameValueCollection query, ref ProfileItem item)
|
||||
{
|
||||
item.Flow = GetQueryValue(query, "flow");
|
||||
item.StreamSecurity = GetQueryValue(query, "security");
|
||||
item.Sni = GetQueryValue(query, "sni");
|
||||
item.Alpn = GetQueryDecoded(query, "alpn");
|
||||
item.Fingerprint = GetQueryDecoded(query, "fp");
|
||||
item.PublicKey = GetQueryDecoded(query, "pbk");
|
||||
item.ShortId = GetQueryDecoded(query, "sid");
|
||||
item.SpiderX = GetQueryDecoded(query, "spx");
|
||||
item.Mldsa65Verify = GetQueryDecoded(query, "pqv");
|
||||
item.AllowInsecure = new[] { "allowInsecure", "allow_insecure", "insecure" }.Any(k => (query[k] ?? "") == "1") ? "true" : "";
|
||||
item.Flow = query["flow"] ?? "";
|
||||
item.StreamSecurity = query["security"] ?? "";
|
||||
item.Sni = query["sni"] ?? "";
|
||||
item.Alpn = Utils.UrlDecode(query["alpn"] ?? "");
|
||||
item.Fingerprint = Utils.UrlDecode(query["fp"] ?? "");
|
||||
item.PublicKey = Utils.UrlDecode(query["pbk"] ?? "");
|
||||
item.ShortId = Utils.UrlDecode(query["sid"] ?? "");
|
||||
item.SpiderX = Utils.UrlDecode(query["spx"] ?? "");
|
||||
item.Mldsa65Verify = Utils.UrlDecode(query["pqv"] ?? "");
|
||||
item.AllowInsecure = (query["allowInsecure"] ?? "") == "1" ? "true" : "";
|
||||
|
||||
item.Network = GetQueryValue(query, "type", nameof(ETransport.tcp));
|
||||
item.Network = query["type"] ?? nameof(ETransport.tcp);
|
||||
switch (item.Network)
|
||||
{
|
||||
case nameof(ETransport.tcp):
|
||||
item.HeaderType = GetQueryValue(query, "headerType", Global.None);
|
||||
item.RequestHost = GetQueryDecoded(query, "host");
|
||||
item.HeaderType = query["headerType"] ?? Global.None;
|
||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||
|
||||
break;
|
||||
|
||||
case nameof(ETransport.kcp):
|
||||
item.HeaderType = GetQueryValue(query, "headerType", Global.None);
|
||||
item.Path = GetQueryDecoded(query, "seed");
|
||||
item.HeaderType = query["headerType"] ?? Global.None;
|
||||
item.Path = Utils.UrlDecode(query["seed"] ?? "");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.ws):
|
||||
case nameof(ETransport.httpupgrade):
|
||||
item.RequestHost = GetQueryDecoded(query, "host");
|
||||
item.Path = GetQueryDecoded(query, "path", "/");
|
||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.xhttp):
|
||||
item.RequestHost = GetQueryDecoded(query, "host");
|
||||
item.Path = GetQueryDecoded(query, "path", "/");
|
||||
item.HeaderType = GetQueryDecoded(query, "mode");
|
||||
item.Extra = GetQueryDecoded(query, "extra");
|
||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
||||
item.HeaderType = Utils.UrlDecode(query["mode"] ?? "");
|
||||
item.Extra = Utils.UrlDecode(query["extra"] ?? "");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.http):
|
||||
case nameof(ETransport.h2):
|
||||
item.Network = nameof(ETransport.h2);
|
||||
item.RequestHost = GetQueryDecoded(query, "host");
|
||||
item.Path = GetQueryDecoded(query, "path", "/");
|
||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.quic):
|
||||
item.HeaderType = GetQueryValue(query, "headerType", Global.None);
|
||||
item.RequestHost = GetQueryValue(query, "quicSecurity", Global.None);
|
||||
item.Path = GetQueryDecoded(query, "key");
|
||||
item.HeaderType = query["headerType"] ?? Global.None;
|
||||
item.RequestHost = query["quicSecurity"] ?? Global.None;
|
||||
item.Path = Utils.UrlDecode(query["key"] ?? "");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.grpc):
|
||||
item.RequestHost = GetQueryDecoded(query, "authority");
|
||||
item.Path = GetQueryDecoded(query, "serviceName");
|
||||
item.HeaderType = GetQueryDecoded(query, "mode", Global.GrpcGunMode);
|
||||
item.RequestHost = Utils.UrlDecode(query["authority"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["serviceName"] ?? "");
|
||||
item.HeaderType = Utils.UrlDecode(query["mode"] ?? Global.GrpcGunMode);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -238,14 +239,4 @@ public class BaseFmt
|
|||
var url = $"{Utils.UrlEncode(userInfo)}@{GetIpv6(address)}:{port}";
|
||||
return $"{Global.ProtocolShares[eConfigType]}{url}{query}{remark}";
|
||||
}
|
||||
|
||||
protected static string GetQueryValue(NameValueCollection query, string key, string defaultValue = "")
|
||||
{
|
||||
return query[key] ?? defaultValue;
|
||||
}
|
||||
|
||||
protected static string GetQueryDecoded(NameValueCollection query, string key, string defaultValue = "")
|
||||
{
|
||||
return Utils.UrlDecode(GetQueryValue(query, key, defaultValue));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ public class Hysteria2Fmt : BaseFmt
|
|||
|
||||
var query = Utils.ParseQueryString(url.Query);
|
||||
ResolveStdTransport(query, ref item);
|
||||
item.Path = GetQueryDecoded(query, "obfs-password");
|
||||
item.AllowInsecure = GetQueryValue(query, "insecure") == "1" ? "true" : "false";
|
||||
item.Path = Utils.UrlDecode(query["obfs-password"] ?? "");
|
||||
item.AllowInsecure = (query["insecure"] ?? "") == "1" ? "true" : "false";
|
||||
|
||||
item.Ports = GetQueryDecoded(query, "mport");
|
||||
item.Ports = Utils.UrlDecode(query["mport"] ?? "");
|
||||
|
||||
return item;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class TuicFmt : BaseFmt
|
|||
|
||||
var query = Utils.ParseQueryString(url.Query);
|
||||
ResolveStdTransport(query, ref item);
|
||||
item.HeaderType = GetQueryValue(query, "congestion_control");
|
||||
item.HeaderType = query["congestion_control"] ?? "";
|
||||
|
||||
return item;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ public class VLESSFmt : BaseFmt
|
|||
item.Id = Utils.UrlDecode(url.UserInfo);
|
||||
|
||||
var query = Utils.ParseQueryString(url.Query);
|
||||
item.Security = GetQueryValue(query, "encryption", Global.None);
|
||||
item.StreamSecurity = GetQueryValue(query, "security");
|
||||
item.Security = query["encryption"] ?? Global.None;
|
||||
item.StreamSecurity = query["security"] ?? "";
|
||||
_ = ResolveStdTransport(query, ref item);
|
||||
|
||||
return item;
|
||||
|
|
|
@ -24,10 +24,10 @@ public class WireguardFmt : BaseFmt
|
|||
|
||||
var query = Utils.ParseQueryString(url.Query);
|
||||
|
||||
item.PublicKey = GetQueryDecoded(query, "publickey");
|
||||
item.Path = GetQueryDecoded(query, "reserved");
|
||||
item.RequestHost = GetQueryDecoded(query, "address");
|
||||
item.ShortId = GetQueryDecoded(query, "mtu");
|
||||
item.PublicKey = Utils.UrlDecode(query["publickey"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["reserved"] ?? "");
|
||||
item.RequestHost = Utils.UrlDecode(query["address"] ?? "");
|
||||
item.ShortId = Utils.UrlDecode(query["mtu"] ?? "");
|
||||
|
||||
return item;
|
||||
}
|
||||
|
|
11
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
11
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
@ -3076,7 +3076,16 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Resolve DNS server domains, requires IP 的本地化字符串。
|
||||
/// 查找类似 The sing-box DoH resolution server can be overwritten 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBDoHOverride {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBDoHOverride", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Fallback DNS Resolution, Require IP 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBFallbackDNSResolve {
|
||||
get {
|
||||
|
|
|
@ -1429,7 +1429,7 @@
|
|||
<value>Bootstrap DNS (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Resolve DNS server domains, requires IP</value>
|
||||
<value>Fallback DNS Resolution, Require IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
|
@ -1443,6 +1443,9 @@
|
|||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
|
|
|
@ -1429,7 +1429,7 @@
|
|||
<value>Bootstrap DNS (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Resolve DNS server domains, requires IP</value>
|
||||
<value>Fallback DNS Resolution, Require IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
|
@ -1443,6 +1443,9 @@
|
|||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
|
|
|
@ -1429,7 +1429,7 @@
|
|||
<value>Bootstrap DNS (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Resolve DNS server domains, requires IP</value>
|
||||
<value>Fallback DNS Resolution, Require IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
|
@ -1443,6 +1443,9 @@
|
|||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
|
|
|
@ -1429,7 +1429,7 @@
|
|||
<value>Bootstrap DNS (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Resolve DNS server domains, requires IP</value>
|
||||
<value>Fallback DNS Resolution, Require IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>Стратегия резолвинга Freedom (Xray)</value>
|
||||
|
@ -1443,6 +1443,9 @@
|
|||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Добавить стандартные записи hosts (DNS)</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>Сервер DoH-резолвера sing-box можно переопределить</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
|
|
|
@ -1426,7 +1426,7 @@
|
|||
<value>Bootstrap DNS (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>解析 DNS 服务器域名,需指定为 IP</value>
|
||||
<value>回退 DNS 解析,需指定为 IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray freedom 解析策略</value>
|
||||
|
@ -1440,6 +1440,9 @@
|
|||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>添加常用 DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>开启后可覆盖 sing-box DoH 解析服务器</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
|
|
|
@ -1426,7 +1426,7 @@
|
|||
<value>Bootstrap DNS (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Resolve DNS server domains, requires IP</value>
|
||||
<value>Fallback DNS Resolution, Require IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
|
@ -1440,6 +1440,9 @@
|
|||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
|
|
|
@ -177,7 +177,7 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
|
||||
ret.Success = true;
|
||||
|
||||
ret.Data = await ApplyFullConfigTemplate(v2rayConfig);
|
||||
ret.Data = await ApplyFullConfigTemplate(v2rayConfig, true);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -234,7 +234,7 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
|
||||
ret.Success = true;
|
||||
|
||||
ret.Data = await ApplyFullConfigTemplate(v2rayConfig);
|
||||
ret.Data = await ApplyFullConfigTemplate(v2rayConfig, true);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace ServiceLib.Services.CoreConfig;
|
|||
|
||||
public partial class CoreConfigV2rayService
|
||||
{
|
||||
private async Task<string> ApplyFullConfigTemplate(V2rayConfig v2rayConfig)
|
||||
private async Task<string> ApplyFullConfigTemplate(V2rayConfig v2rayConfig, bool handleBalancerAndRules = false)
|
||||
{
|
||||
var fullConfigTemplate = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
if (fullConfigTemplate == null || !fullConfigTemplate.Enabled || fullConfigTemplate.Config.IsNullOrEmpty())
|
||||
|
@ -19,7 +19,7 @@ public partial class CoreConfigV2rayService
|
|||
}
|
||||
|
||||
// Handle balancer and rules modifications (for multiple load scenarios)
|
||||
if (v2rayConfig.routing?.balancers?.Count > 0)
|
||||
if (handleBalancerAndRules && v2rayConfig.routing?.balancers?.Count > 0)
|
||||
{
|
||||
var balancer = v2rayConfig.routing.balancers.First();
|
||||
|
||||
|
@ -60,34 +60,6 @@ public partial class CoreConfigV2rayService
|
|||
}
|
||||
}
|
||||
|
||||
if (v2rayConfig.observatory != null)
|
||||
{
|
||||
if (fullConfigTemplateNode["observatory"] == null)
|
||||
{
|
||||
fullConfigTemplateNode["observatory"] = JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.observatory));
|
||||
}
|
||||
else
|
||||
{
|
||||
var subjectSelector = v2rayConfig.observatory.subjectSelector;
|
||||
subjectSelector.AddRange(fullConfigTemplateNode["observatory"]?["subjectSelector"]?.AsArray()?.Select(x => x?.GetValue<string>()) ?? []);
|
||||
fullConfigTemplateNode["observatory"]["subjectSelector"] = JsonNode.Parse(JsonUtils.Serialize(subjectSelector.Distinct().ToList()));
|
||||
}
|
||||
}
|
||||
|
||||
if (v2rayConfig.burstObservatory != null)
|
||||
{
|
||||
if (fullConfigTemplateNode["burstObservatory"] == null)
|
||||
{
|
||||
fullConfigTemplateNode["burstObservatory"] = JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.burstObservatory));
|
||||
}
|
||||
else
|
||||
{
|
||||
var subjectSelector = v2rayConfig.burstObservatory.subjectSelector;
|
||||
subjectSelector.AddRange(fullConfigTemplateNode["burstObservatory"]?["subjectSelector"]?.AsArray()?.Select(x => x?.GetValue<string>()) ?? []);
|
||||
fullConfigTemplateNode["burstObservatory"]["subjectSelector"] = JsonNode.Parse(JsonUtils.Serialize(subjectSelector.Distinct().ToList()));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle outbounds - append instead of override
|
||||
var customOutboundsNode = fullConfigTemplateNode["outbounds"] is JsonArray outbounds ? outbounds : new JsonArray();
|
||||
foreach (var outbound in v2rayConfig.outbounds)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceInclude Source="Assets/GlobalResources.axaml" />
|
||||
<ResourceInclude Source="Controls/AutoCompleteBox.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
|
||||
|
@ -19,7 +18,7 @@ internal class AvaUtils
|
|||
return null;
|
||||
}
|
||||
|
||||
return await clipboard.TryGetTextAsync();
|
||||
return await clipboard.GetTextAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -34,7 +33,9 @@ internal class AvaUtils
|
|||
var clipboard = TopLevel.GetTopLevel(visual)?.Clipboard;
|
||||
if (clipboard == null)
|
||||
return;
|
||||
await clipboard.SetTextAsync(strData);
|
||||
var dataObject = new DataObject();
|
||||
dataObject.Set(DataFormats.Text, strData);
|
||||
await clipboard.SetDataObjectAsync(dataObject);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
48
v2rayN/v2rayN.Desktop/Controls/AutoCompleteBox.axaml
Normal file
48
v2rayN/v2rayN.Desktop/Controls/AutoCompleteBox.axaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:v2rayN.Desktop.Controls">
|
||||
<!-- Add Resources Here -->
|
||||
<ControlTheme x:Key="{x:Type controls:AutoCompleteBox}" TargetType="controls:AutoCompleteBox">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="MinHeight" Value="{DynamicResource AutoCompleteBoxDefaultHeight}" />
|
||||
<Setter Property="MaxDropDownHeight" Value="{DynamicResource AutoCompleteMaxDropdownHeight}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="AutoCompleteBox">
|
||||
<Panel>
|
||||
<TextBox
|
||||
Name="PART_TextBox"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
VerticalAlignment="Stretch"
|
||||
DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}"
|
||||
InnerLeftContent="{TemplateBinding InnerLeftContent}"
|
||||
InnerRightContent="{TemplateBinding InnerRightContent}"
|
||||
Watermark="{TemplateBinding Watermark}" />
|
||||
<Popup
|
||||
Name="PART_Popup"
|
||||
MaxHeight="{TemplateBinding MaxDropDownHeight}"
|
||||
IsLightDismissEnabled="True"
|
||||
PlacementTarget="{TemplateBinding}">
|
||||
<Border
|
||||
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Margin="{DynamicResource AutoCompleteBoxPopupMargin}"
|
||||
Padding="{DynamicResource AutoCompleteBoxPopupPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource AutoCompleteBoxPopupBackground}"
|
||||
BorderBrush="{DynamicResource AutoCompleteBoxPopupBorderBrush}"
|
||||
BorderThickness="{DynamicResource AutoCompleteBoxPopupBorderThickness}"
|
||||
BoxShadow="{DynamicResource AutoCompleteBoxPopupBoxShadow}"
|
||||
CornerRadius="{DynamicResource AutoCompleteBoxPopupCornerRadius}">
|
||||
<ListBox
|
||||
Name="PART_SelectingItemsControl"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
ItemTemplate="{TemplateBinding ItemTemplate}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto" />
|
||||
</Border>
|
||||
</Popup>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
40
v2rayN/v2rayN.Desktop/Controls/AutoCompleteBox.cs
Normal file
40
v2rayN/v2rayN.Desktop/Controls/AutoCompleteBox.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace v2rayN.Desktop.Controls;
|
||||
|
||||
public class AutoCompleteBox : Avalonia.Controls.AutoCompleteBox
|
||||
{
|
||||
static AutoCompleteBox()
|
||||
{
|
||||
MinimumPrefixLengthProperty.OverrideDefaultValue<AutoCompleteBox>(0);
|
||||
}
|
||||
|
||||
public AutoCompleteBox()
|
||||
{
|
||||
AddHandler(PointerPressedEvent, OnBoxPointerPressed, RoutingStrategies.Tunnel);
|
||||
}
|
||||
|
||||
private void OnBoxPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (Equals(sender, this) && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
SetCurrentValue(IsDropDownOpenProperty, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGotFocus(GotFocusEventArgs e)
|
||||
{
|
||||
base.OnGotFocus(e);
|
||||
if (IsDropDownOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SetCurrentValue(IsDropDownOpenProperty, true);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SetCurrentValue(SelectedItemProperty, null);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
x:Class="v2rayN.Desktop.Views.DNSSettingWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ctrls="clr-namespace:v2rayN.Desktop.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
|
@ -55,13 +56,13 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbDomesticDNS}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbDirectDNS"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding DirectDNS, Mode=TwoWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
|
@ -69,13 +70,13 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbRemoteDNS}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbRemoteDNS"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding RemoteDNS, Mode=TwoWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
|
@ -83,13 +84,13 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbSBResolverDNS"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding SingboxOutboundsResolveDNS, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
|
@ -104,13 +105,13 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBBootstrapDNS}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbSBFinalResolverDNS"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding SingboxFinalResolveDNS, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
|
@ -173,6 +174,13 @@
|
|||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBDoHOverride}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
@ -252,13 +260,13 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPs}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbDirectExpectedIPs"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding DirectExpectedIPs, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
|
@ -355,11 +363,11 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbdomainDNSAddressCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding DomainDNSAddressCompatible, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
|
@ -427,11 +435,11 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbdomainDNSAddress2Compatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding DomainDNSAddress2Compatible, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
|
|
|
@ -40,15 +40,15 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
|||
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RayStrategy4Freedom, v => v.cmbRayFreedomDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxStrategy4Direct, v => v.cmbSBDirectDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxStrategy4Proxy, v => v.cmbSBRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
|
||||
|
@ -57,11 +57,11 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
|||
|
||||
this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables);
|
||||
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.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.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);
|
||||
//this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
x:Class="v2rayN.Desktop.Views.OptionSettingWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ctrls="clr-namespace:v2rayN.Desktop.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
|
@ -501,13 +502,12 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbcurrentFontFamily"
|
||||
Grid.Row="15"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
<TextBlock
|
||||
Grid.Row="15"
|
||||
Grid.Column="2"
|
||||
|
@ -548,13 +548,12 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsSpeedTestUrl}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
Name="cmbSpeedTestUrl"
|
||||
Grid.Row="18"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="19"
|
||||
|
@ -562,13 +561,12 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsSpeedPingTestUrl}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbSpeedPingTestUrl"
|
||||
Grid.Row="19"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="20"
|
||||
|
@ -589,13 +587,12 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsSubConvert}" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbSubConvertUrl"
|
||||
Grid.Row="21"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="22"
|
||||
|
@ -621,8 +618,7 @@
|
|||
Grid.Row="23"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
<TextBlock
|
||||
Grid.Row="23"
|
||||
Grid.Column="2"
|
||||
|
@ -642,8 +638,7 @@
|
|||
Grid.Row="24"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
<TextBlock
|
||||
Grid.Row="24"
|
||||
Grid.Column="2"
|
||||
|
@ -663,8 +658,7 @@
|
|||
Grid.Row="25"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Margin="{StaticResource Margin4}" />
|
||||
<TextBlock
|
||||
Grid.Row="25"
|
||||
Grid.Column="2"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
x:Class="v2rayN.Desktop.Views.RoutingRuleDetailsWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ctrls="clr-namespace:v2rayN.Desktop.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
|
@ -46,26 +47,28 @@
|
|||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="outboundTag" />
|
||||
<ComboBox
|
||||
<ctrls:AutoCompleteBox
|
||||
Name="cmbOutboundTag"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}"
|
||||
IsEditable="True" />
|
||||
Text="{Binding SelectedSource.OutboundTag, Mode=TwoWay}" />
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
VerticalAlignment="Center">
|
||||
<Button
|
||||
x:Name="btnSelectProfile"
|
||||
Margin="0,0,8,0"
|
||||
Click="BtnSelectProfile_Click"
|
||||
Content="{x:Static resx:ResUI.TbSelectProfile}" />
|
||||
<TextBlock VerticalAlignment="Center" Text="{x:Static resx:ResUI.TbRuleOutboundTagTip}" />
|
||||
Content="{x:Static resx:ResUI.TbSelectProfile}"
|
||||
Click="BtnSelectProfile_Click" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbRuleOutboundTagTip}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
|
|
|
@ -43,7 +43,6 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
|||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);
|
||||
|
|
|
@ -210,6 +210,13 @@
|
|||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="3"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBDoHOverride}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
|
Loading…
Reference in a new issue