Skip to content

Commit 81f65c2

Browse files
committed
Added SearchableComboBox control
1 parent 8c90b99 commit 81f65c2

File tree

11 files changed

+778
-36
lines changed

11 files changed

+778
-36
lines changed

Aronium.Wpf.Toolkit.Demo/MainWindow.xaml

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
Style="{DynamicResource Window}"
88
SnapsToDevicePixels="True"
99
FocusManager.FocusedElement="{Binding ElementName=cbTabPlacement}"
10+
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
1011
Title="MainWindow" Height="750" Width="950">
1112

1213
<Window.Resources>
@@ -25,6 +26,7 @@
2526
<Style TargetType="{x:Type aronium:SplitButton}" BasedOn="{StaticResource {x:Type aronium:SplitButton}}">
2627
<Setter Property="Height" Value="{StaticResource ButtonHeightGlobal}" />
2728
</Style>
29+
2830
</Window.Resources>
2931

3032
<Grid>
@@ -101,6 +103,13 @@
101103

102104
<TabControl Grid.Row="1" Name="tabControl" SnapsToDevicePixels="True" BorderBrush="{DynamicResource Accent}">
103105
<TabItem Header="Tab item 1">
106+
107+
<TabItem.Resources>
108+
<Style TargetType="{x:Type GroupBox}" BasedOn="{StaticResource {x:Type GroupBox}}">
109+
<Setter Property="Padding" Value="5 2" />
110+
</Style>
111+
</TabItem.Resources>
112+
104113
<ScrollViewer VerticalScrollBarVisibility="Auto">
105114

106115
<Grid>
@@ -144,13 +153,13 @@
144153
</aronium:LiveSearchTextBox.ItemTemplate>
145154
</aronium:LiveSearchTextBox>
146155

147-
<aronium:Callout CalloutType="Info" Margin="5">
156+
<aronium:Callout CalloutType="Info" Margin="0 5">
148157
Info callout
149158
</aronium:Callout>
150-
<aronium:Callout CalloutType="Error" Margin="5">
159+
<aronium:Callout CalloutType="Error" Margin="0 5">
151160
Error callout
152161
</aronium:Callout>
153-
<aronium:Callout CalloutType="Warning" Margin="5">
162+
<aronium:Callout CalloutType="Warning" Margin="0 5">
154163
Warning callout
155164
</aronium:Callout>
156165
</StackPanel>
@@ -160,26 +169,44 @@
160169

161170
<GroupBox Header="Combo Box" Grid.Column="2" SnapsToDevicePixels="True">
162171
<StackPanel>
163-
<ComboBox Margin="0,5" Width="180" HorizontalAlignment="Left">
172+
<ComboBox Margin="0,5">
164173
<ComboBoxItem Content="Item 1" />
165174
<ComboBoxItem Content="Item 2" />
166175
<ComboBoxItem Content="Item 3" />
167176
<ComboBoxItem Content="Item 4" />
168177
<ComboBoxItem Content="Item 5" />
169178
</ComboBox>
170179

171-
<ComboBox IsEditable="True" Margin="0,5" Width="180" HorizontalAlignment="Left">
180+
<ComboBox IsEditable="True" Margin="0,5">
172181
<ComboBoxItem Content="Editable Item 1" />
173182
<ComboBoxItem Content="Editable Item 2" />
174183
<ComboBoxItem Content="Editable Item 3" />
175184
<ComboBoxItem Content="Editable Item 4" />
176185
<ComboBoxItem Content="Editable Item 5" />
177186
</ComboBox>
178187

179-
<ComboBox IsEnabled="False" Margin="0,5" Width="180" HorizontalAlignment="Left">
188+
<ComboBox IsEnabled="False" Margin="0,5">
180189
<ComboBoxItem IsSelected="True" Content="Disabled" />
181190
</ComboBox>
182191

192+
<TextBlock>
193+
<Run Text="Selected country:" />
194+
<Run Text="{Binding SelectedCountry, TargetNullValue='(none)'}" />
195+
</TextBlock>
196+
<aronium:SearchableComboBox Margin="0,5,5,5"
197+
ItemsSource="{Binding Countries}"
198+
Watermark="Search countries..."
199+
NoItemsText="No results"
200+
AllowNullSelection="False">
201+
<ComboBox.SelectedItem>
202+
<Binding Path="SelectedCountry" UpdateSourceTrigger="PropertyChanged">
203+
<Binding.ValidationRules>
204+
<aronium:NotNullValidation ValidatesOnTargetUpdated="True"/>
205+
</Binding.ValidationRules>
206+
</Binding>
207+
</ComboBox.SelectedItem>
208+
</aronium:SearchableComboBox>
209+
183210
<aronium:TextSeparator FontSize="18" FontFamily="Segoe UI Light" Content="Text separator" />
184211

185212
<ProgressBar Value="40" Maximum="100" Margin="0,10" />

Aronium.Wpf.Toolkit.Demo/MainWindow.xaml.cs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ public partial class MainWindow : Window, INotifyPropertyChanged
2626
private string _selectedTag;
2727
List<User> _users;
2828
private string _searchText;
29-
List<string> countries = new List<string>(new[] { "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Anguilla", "Antigua & Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia & Herzegovina", "Botswana", "Brazil", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Myanmar/Burma", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominican Republic", "Dominica", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Fiji", "Finland", "France", "French Guiana", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Great Britain", "Greece", "Grenada", "Guadeloupe", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Israel and the Occupied Territories", "Italy", "Ivory Coast (Cote d'Ivoire)", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kosovo", "Kuwait", "Kyrgyz Republic (Kyrgyzstan)", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Republic of Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Moldova, Republic of", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Namibia", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Korea, Democratic Republic of (North Korea)", "Norway", "Oman", "Pacific Islands", "Pakistan", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation", "Rwanda", "Saint Kitts and Nevis", "Saint Lucia", "Saint Vincent's & Grenadines", "Samoa", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovak Republic (Slovakia)", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "Korea, Republic of (South Korea)", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Swaziland", "Sweden", "Switzerland", "Syria", "Tajikistan", "Tanzania", "Thailand", "Timor Leste", "Togo", "Trinidad & Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks & Caicos Islands", "Uganda", "Ukraine", "United Arab Emirates", "United States of America (USA)", "Uruguay", "Uzbekistan", "Venezuela", "Vietnam", "Virgin Islands (UK)", "Virgin Islands (US)", "Yemen", "Zambia", "Zimbabwe" });
30-
29+
List<string> countries = new List<string>(new[] { "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Anguilla", "Antigua & Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia & Herzegovina", "Botswana", "Brazil", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Myanmar/Burma", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominican Republic", "Dominica", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Fiji", "Finland", "France", "French Guiana", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Great Britain", "Greece", "Grenada", "Guadeloupe", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Israel and the Occupied Territories", "Italy", "Ivory Coast (Cote d'Ivoire)", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kosovo", "Kuwait", "Kyrgyz Republic (Kyrgyzstan)", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Republic of Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Moldova, Republic of", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Namibia", "Nepal", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Korea, Democratic Republic of (North Korea)", "Norway", "Oman", "Pacific Islands", "Pakistan", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation", "Rwanda", "Saint Kitts and Nevis", "Saint Lucia", "Saint Vincent's & Grenadines", "Samoa", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovak Republic (Slovakia)", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "Korea, Republic of (South Korea)", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Swaziland", "Sweden", "Switzerland", "Syria", "Tajikistan", "Tanzania", "Thailand", "Timor Leste", "Togo", "Trinidad & Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks & Caicos Islands", "Uganda", "Ukraine", "United Arab Emirates", "United States of America (USA)", "Uruguay", "Uzbekistan", "Venezuela", "Vietnam", "Virgin Islands (UK)", "Virgin Islands (US)", "Yemen", "Zambia", "Zimbabwe" });
30+
private string countryComboBoxFilter;
31+
private string selectedCountry = "United States of America (USA)";
32+
3133
public MainWindow()
3234
{
3335
InitializeComponent();
3436

3537
Themes = new List<string>(new[] { "Light", "Dark", "Dimmed", "HighContrast", "Gray" });
3638

37-
ThemeName = "Gray";
38-
39-
DataContext = this;
39+
ThemeName = "Dark";
4040

4141
IntegerProperty = new Random().Next(0, 1000);
4242

@@ -222,12 +222,11 @@ public IEnumerable<string> SelectedCountries
222222
get
223223
{
224224
if (!string.IsNullOrEmpty(SearchText))
225-
{
226-
foreach (var country in Countries.Where(x => x.ToUpper().Contains(SearchText.ToUpper())))
227-
{
228-
yield return country;
229-
}
225+
{
226+
return FindCountries(SearchText);
230227
}
228+
229+
return Enumerable.Empty<string>();
231230
}
232231
}
233232

@@ -275,7 +274,7 @@ private void CreateGuidedTour()
275274
};
276275
}
277276

278-
private void OnResetGuide(object sender, RoutedEventArgs e)
277+
private void OnResetGuide(object sender, RoutedEventArgs e)
279278
{
280279
guide.Reset();
281280
}
@@ -332,5 +331,50 @@ protected override void OnKeyDown(KeyEventArgs e)
332331

333332
public ObservableCollection<NotificationItem> Notifications { get; set; } = new ObservableCollection<NotificationItem>();
334333

334+
public string SelectedCountry
335+
{
336+
get => selectedCountry;
337+
set
338+
{
339+
selectedCountry = value;
340+
OnPropertyChanged(nameof(SelectedCountry));
341+
}
342+
}
343+
344+
public string CountryComboBoxFilter
345+
{
346+
get => countryComboBoxFilter;
347+
set
348+
{
349+
countryComboBoxFilter = value;
350+
}
351+
}
352+
353+
public IEnumerable<string> FilteredCountries
354+
{
355+
get
356+
{
357+
return FindCountries(CountryComboBoxFilter);
358+
}
359+
}
360+
361+
private IEnumerable<string> FindCountries(string input)
362+
{
363+
input = input?.ToUpper();
364+
365+
foreach (var country in countries)
366+
{
367+
if (string.IsNullOrEmpty(input) || country.ToUpper().Contains(input))
368+
{
369+
yield return country;
370+
}
371+
}
372+
}
373+
374+
private void OnSearchChanged(object sender, SearchTextChangedEventArgs e)
375+
{
376+
countryComboBoxFilter = e.Value;
377+
OnPropertyChanged(nameof(FilteredCountries));
378+
}
335379
}
336380
}

Aronium.Wpf.Toolkit/Aronium.Wpf.Toolkit.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
44
<PropertyGroup>
@@ -75,6 +75,7 @@
7575
<Compile Include="Controls\NotificationsControl.cs" />
7676
<Compile Include="Controls\NotificationItem.cs" />
7777
<Compile Include="Controls\Rating.cs" />
78+
<Compile Include="Controls\SearchableComboBox.cs" />
7879
<Compile Include="Controls\TagItem.cs" />
7980
<Compile Include="Controls\TagControl.cs" />
8081
<Compile Include="Controls\ToggleSwitch.cs" />
@@ -103,6 +104,7 @@
103104
<DesignTimeSharedInput>True</DesignTimeSharedInput>
104105
</Compile>
105106
<Compile Include="Validators\EmptyValidationRule.cs" />
107+
<Compile Include="Validators\NotNullValidation.cs" />
106108
<Compile Include="Validators\NumericValidationRule.cs" />
107109
<Compile Include="Helpers\VisualHelper.cs" />
108110
<EmbeddedResource Include="Properties\Resources.resx">
@@ -157,6 +159,10 @@
157159
<Generator>MSBuild:Compile</Generator>
158160
<SubType>Designer</SubType>
159161
</Page>
162+
<Page Include="Themes\SearchableComboBoxStyle.xaml">
163+
<Generator>MSBuild:Compile</Generator>
164+
<SubType>Designer</SubType>
165+
</Page>
160166
<Page Include="Themes\ComboBoxStyle.xaml">
161167
<SubType>Designer</SubType>
162168
<Generator>MSBuild:Compile</Generator>

Aronium.Wpf.Toolkit/Controls/ButtonGroup.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Windows;
1+
using System.Windows;
62
using System.Windows.Controls;
73
using System.Windows.Controls.Primitives;
84

Aronium.Wpf.Toolkit/Controls/LiveSearchTextBox.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,6 @@ private void OnTextBoxPreviewKeyDown(object sender, KeyEventArgs e)
180180
}
181181
}
182182

183-
private void FocusSelectedListBoxItem()
184-
{
185-
var element = GetListBoxElementFromSelectedItem(listBox.SelectedItem);
186-
187-
if (element != null)
188-
{
189-
element.Focus();
190-
Keyboard.Focus(element);
191-
}
192-
}
193-
194183
private ListBoxItem GetListBoxElementFromSelectedItem(object item)
195184
{
196185
return listBox.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;

0 commit comments

Comments
 (0)