Skip to content

Commit 2e962e5

Browse files
committed
Use AutoCompleteBox instead of editable Combobox for desktop
Thanks to https://github.com/irihitech/Ursa.Avalonia
1 parent ab73e5a commit 2e962e5

File tree

5 files changed

+111
-33
lines changed

5 files changed

+111
-33
lines changed

v2rayN/v2rayN.Desktop/App.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<ResourceDictionary>
2020
<ResourceDictionary.MergedDictionaries>
2121
<ResourceInclude Source="Assets/GlobalResources.axaml" />
22+
<ResourceInclude Source="Controls/AutoCompleteBox.axaml" />
2223
</ResourceDictionary.MergedDictionaries>
2324
</ResourceDictionary>
2425
</Application.Resources>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<ResourceDictionary
2+
xmlns="https://github.com/avaloniaui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:controls="clr-namespace:v2rayN.Desktop.Controls">
5+
<!-- Add Resources Here -->
6+
<ControlTheme x:Key="{x:Type controls:AutoCompleteBox}" TargetType="controls:AutoCompleteBox">
7+
<Setter Property="VerticalAlignment" Value="Center" />
8+
<Setter Property="MinHeight" Value="{DynamicResource AutoCompleteBoxDefaultHeight}" />
9+
<Setter Property="MaxDropDownHeight" Value="{DynamicResource AutoCompleteMaxDropdownHeight}" />
10+
<Setter Property="Template">
11+
<ControlTemplate TargetType="AutoCompleteBox">
12+
<Panel>
13+
<TextBox
14+
Name="PART_TextBox"
15+
MinHeight="{TemplateBinding MinHeight}"
16+
VerticalAlignment="Stretch"
17+
DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}"
18+
InnerLeftContent="{TemplateBinding InnerLeftContent}"
19+
InnerRightContent="{TemplateBinding InnerRightContent}"
20+
Watermark="{TemplateBinding Watermark}" />
21+
<Popup
22+
Name="PART_Popup"
23+
MaxHeight="{TemplateBinding MaxDropDownHeight}"
24+
IsLightDismissEnabled="True"
25+
PlacementTarget="{TemplateBinding}">
26+
<Border
27+
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
28+
Margin="{DynamicResource AutoCompleteBoxPopupMargin}"
29+
Padding="{DynamicResource AutoCompleteBoxPopupPadding}"
30+
HorizontalAlignment="Stretch"
31+
Background="{DynamicResource AutoCompleteBoxPopupBackground}"
32+
BorderBrush="{DynamicResource AutoCompleteBoxPopupBorderBrush}"
33+
BorderThickness="{DynamicResource AutoCompleteBoxPopupBorderThickness}"
34+
BoxShadow="{DynamicResource AutoCompleteBoxPopupBoxShadow}"
35+
CornerRadius="{DynamicResource AutoCompleteBoxPopupCornerRadius}">
36+
<ListBox
37+
Name="PART_SelectingItemsControl"
38+
Foreground="{TemplateBinding Foreground}"
39+
ItemTemplate="{TemplateBinding ItemTemplate}"
40+
ScrollViewer.HorizontalScrollBarVisibility="Auto"
41+
ScrollViewer.VerticalScrollBarVisibility="Auto" />
42+
</Border>
43+
</Popup>
44+
</Panel>
45+
</ControlTemplate>
46+
</Setter>
47+
</ControlTheme>
48+
</ResourceDictionary>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Avalonia.Input;
2+
using Avalonia.Interactivity;
3+
4+
namespace v2rayN.Desktop.Controls;
5+
6+
public class AutoCompleteBox : Avalonia.Controls.AutoCompleteBox
7+
{
8+
static AutoCompleteBox()
9+
{
10+
MinimumPrefixLengthProperty.OverrideDefaultValue<AutoCompleteBox>(0);
11+
}
12+
13+
public AutoCompleteBox()
14+
{
15+
AddHandler(PointerPressedEvent, OnBoxPointerPressed, RoutingStrategies.Tunnel);
16+
}
17+
18+
private void OnBoxPointerPressed(object? sender, PointerPressedEventArgs e)
19+
{
20+
if (Equals(sender, this) && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
21+
{
22+
SetCurrentValue(IsDropDownOpenProperty, true);
23+
}
24+
}
25+
26+
protected override void OnGotFocus(GotFocusEventArgs e)
27+
{
28+
base.OnGotFocus(e);
29+
if (IsDropDownOpen)
30+
return;
31+
SetCurrentValue(IsDropDownOpenProperty, true);
32+
}
33+
34+
public void Clear()
35+
{
36+
SetCurrentValue(SelectedItemProperty, null);
37+
}
38+
}

v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
x:Class="v2rayN.Desktop.Views.OptionSettingWindow"
33
xmlns="https://github.com/avaloniaui"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:ctrls="clr-namespace:v2rayN.Desktop.Controls"
56
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
67
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
78
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
@@ -219,8 +220,7 @@
219220
Grid.Row="13"
220221
Grid.Column="1"
221222
Width="200"
222-
Classes="Margin8"
223-
ToolTip.Tip="Level" />
223+
Classes="Margin8" />
224224

225225
<TextBlock
226226
Grid.Row="14"
@@ -505,13 +505,12 @@
505505
VerticalAlignment="Center"
506506
Classes="Margin8"
507507
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" />
508-
<ComboBox
508+
<ctrls:AutoCompleteBox
509509
x:Name="cmbcurrentFontFamily"
510510
Grid.Row="15"
511511
Grid.Column="1"
512-
Width="200"
513-
Classes="Margin8"
514-
MaxDropDownHeight="1000" />
512+
Width="300"
513+
Classes="Margin8" />
515514
<TextBlock
516515
Grid.Row="15"
517516
Grid.Column="2"
@@ -552,8 +551,8 @@
552551
VerticalAlignment="Center"
553552
Classes="Margin8"
554553
Text="{x:Static resx:ResUI.TbSettingsSpeedTestUrl}" />
555-
<ComboBox
556-
x:Name="cmbSpeedTestUrl"
554+
<ctrls:AutoCompleteBox
555+
Name="cmbSpeedTestUrl"
557556
Grid.Row="18"
558557
Grid.Column="1"
559558
Width="300"
@@ -565,7 +564,7 @@
565564
VerticalAlignment="Center"
566565
Classes="Margin8"
567566
Text="{x:Static resx:ResUI.TbSettingsSpeedPingTestUrl}" />
568-
<ComboBox
567+
<ctrls:AutoCompleteBox
569568
x:Name="cmbSpeedPingTestUrl"
570569
Grid.Row="19"
571570
Grid.Column="1"
@@ -578,13 +577,12 @@
578577
VerticalAlignment="Center"
579578
Classes="Margin8"
580579
Text="{x:Static resx:ResUI.TbSettingsSubConvert}" />
581-
<ComboBox
580+
<ctrls:AutoCompleteBox
582581
x:Name="cmbSubConvertUrl"
583582
Grid.Row="20"
584583
Grid.Column="1"
585584
Width="300"
586-
Classes="Margin8"
587-
ToolTip.Tip="Convert Url" />
585+
Classes="Margin8" />
588586

589587
<TextBlock
590588
Grid.Row="21"
@@ -596,7 +594,7 @@
596594
x:Name="cmbMainGirdOrientation"
597595
Grid.Row="21"
598596
Grid.Column="1"
599-
Width="300"
597+
Width="200"
600598
Classes="Margin8" />
601599

602600
<TextBlock
@@ -687,8 +685,7 @@
687685
<ComboBox
688686
x:Name="cmbsystemProxyAdvancedProtocol"
689687
MinWidth="400"
690-
Classes="Margin8"
691-
ToolTip.Tip="Protocol" />
688+
Classes="Margin8" />
692689
</StackPanel>
693690
</StackPanel>
694691

v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,11 @@ public OptionSettingWindow()
7474
{
7575
cmbSpeedTestTimeout.Items.Add(i * 5);
7676
}
77-
Global.SpeedTestUrls.ForEach(it =>
78-
{
79-
cmbSpeedTestUrl.Items.Add(it);
80-
});
81-
Global.SpeedPingTestUrls.ForEach(it =>
82-
{
83-
cmbSpeedPingTestUrl.Items.Add(it);
84-
});
85-
Global.SubConvertUrls.ForEach(it =>
86-
{
87-
cmbSubConvertUrl.Items.Add(it);
88-
});
77+
78+
cmbSpeedTestUrl.ItemsSource = Global.SpeedTestUrls;
79+
cmbSpeedPingTestUrl.ItemsSource = Global.SpeedPingTestUrls;
80+
cmbSubConvertUrl.ItemsSource = Global.SubConvertUrls;
81+
8982
Global.GeoFilesSources.ForEach(it =>
9083
{
9184
cmbGetFilesSourceUrl.Items.Add(it);
@@ -139,12 +132,12 @@ public OptionSettingWindow()
139132
this.Bind(ViewModel, vm => vm.Hide2TrayWhenClose, v => v.togHide2TrayWhenClose.IsChecked).DisposeWith(disposables);
140133
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
141134
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
142-
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
135+
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.Text).DisposeWith(disposables);
143136
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables);
144-
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables);
145-
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
137+
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
138+
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
146139
this.Bind(ViewModel, vm => vm.MixedConcurrencyCount, v => v.cmbMixedConcurrencyCount.SelectedValue).DisposeWith(disposables);
147-
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables);
140+
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
148141
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
149142
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
150143
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.SelectedValue).DisposeWith(disposables);
@@ -215,8 +208,9 @@ private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
215208
private async Task InitSettingFont()
216209
{
217210
var lstFonts = await GetFonts();
218-
lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
219-
cmbcurrentFontFamily.Items.Add(string.Empty);
211+
212+
lstFonts.Add(string.Empty);
213+
cmbcurrentFontFamily.ItemsSource = lstFonts;
220214
}
221215

222216
private async Task<List<string>> GetFonts()

0 commit comments

Comments
 (0)