update inputable dropdown

This commit is contained in:
kwan.nguyen 2024-12-06 02:09:21 +07:00
parent d7bbfca952
commit b8f10e72d7
5 changed files with 84 additions and 9 deletions

View File

@ -1,11 +1,8 @@
using PCUT.Extensions; using PCUT.Extensions;
using PCUT.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Controls.Primitives;
@ -52,6 +49,19 @@ namespace PCUT.Models
if (selector != null) if (selector != null)
selector.SelectionChanged += Selector_SelectionChanged; selector.SelectionChanged += Selector_SelectionChanged;
} }
public virtual void Bind(AutoSuggestBox autoSuggestBox, bool validateMemberPath = true)
{
if (validateMemberPath && string.IsNullOrEmpty(autoSuggestBox.TextMemberPath))
throw new ArgumentException("Cannot bind auto suggestion box with default binding strategy. TextMemberPath is null");
autoSuggestBox.TextChanged += AutoSuggestBoxTextChanged;
autoSuggestBox.SuggestionChosen += AutoSuggestBoxSuggestionChosen;
autoSuggestBox.QuerySubmitted += AutoSuggestBoxQuerySubmitted;
}
protected virtual void AutoSuggestBoxTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) { }
protected virtual void AutoSuggestBoxSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) { }
protected virtual void AutoSuggestBoxQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) { }
} }
public class SelectableCollection<T> : SelectableCollection public class SelectableCollection<T> : SelectableCollection
@ -62,6 +72,8 @@ namespace PCUT.Models
public ObservableCollection<T> Items { get; } public ObservableCollection<T> Items { get; }
public T SelectedItem => _selectedIndex >= 0 ? Items[_selectedIndex] : default; public T SelectedItem => _selectedIndex >= 0 ? Items[_selectedIndex] : default;
private Func<T, string> _propertySelector;
public SelectableCollection(T defaultItem) : base(true) public SelectableCollection(T defaultItem) : base(true)
{ {
DefaultItem = defaultItem; DefaultItem = defaultItem;
@ -127,6 +139,70 @@ namespace PCUT.Models
{ {
var start = _withDefault ? 1 : 0; var start = _withDefault ? 1 : 0;
Items.Filter(_items, filter, start); Items.Filter(_items, filter, start);
_selectedIndex = -2; // set to -2 so that the next select will trigger property changed event
}
public void Bind(AutoSuggestBox autoSuggestBox, Func<T, string> propertySelector)
{
_propertySelector = propertySelector;
base.Bind(autoSuggestBox, validateMemberPath: propertySelector is null);
}
protected override void AutoSuggestBoxTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
Predicate<T> filter;
if (string.IsNullOrEmpty(sender.Text))
{
filter = x => true;
}
else if (_propertySelector != null)
{
filter = x => _propertySelector.Invoke(x)?.StartsWith(sender.Text) ?? false;
}
else
{
var propertyInfo = typeof(T).GetProperty(sender.TextMemberPath, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
filter = x => propertyInfo.GetValue(x)?.ToString()?.StartsWith(sender.Text) ?? false;
}
Filter(filter);
}
}
protected override void AutoSuggestBoxSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
{
}
protected override void AutoSuggestBoxQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (string.IsNullOrEmpty(args.QueryText))
{
SelectedIndex = -1;
}
else if (args.ChosenSuggestion != null)
{
SelectedIndex = Items.IndexOf((T)args.ChosenSuggestion);
}
else
{
Func<T, bool> filter;
if (_propertySelector != null)
{
filter = x => _propertySelector.Invoke(x) == sender.Text;
}
else
{
var propertyInfo = typeof(T).GetProperty(sender.TextMemberPath, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
filter = x => propertyInfo.GetValue(x)?.ToString() == sender.Text;
}
var item = Items.FirstOrDefault(filter);
if (item != null)
{
SelectedIndex = Items.IndexOf(item);
}
}
} }
} }
} }

View File

@ -9,7 +9,7 @@
<Identity <Identity
Name="ac171214-3336-4e02-845d-9bdc107cce71" Name="ac171214-3336-4e02-845d-9bdc107cce71"
Publisher="CN=pcut, O=PCUT, L=HN, S=HN, C=VN" Publisher="CN=pcut, O=PCUT, L=HN, S=HN, C=VN"
Version="1.3.4.10" /> Version="1.3.4.12" />
<mp:PhoneIdentity PhoneProductId="ac171214-3336-4e02-845d-9bdc107cce71" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> <mp:PhoneIdentity PhoneProductId="ac171214-3336-4e02-845d-9bdc107cce71" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

View File

@ -37,14 +37,13 @@
<ColumnDefinition Width="0.15*" /> <ColumnDefinition Width="0.15*" />
<ColumnDefinition Width="0.15*"/> <ColumnDefinition Width="0.15*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<ComboBox <AutoSuggestBox
Grid.Column="1" Grid.Column="1"
x:Name="Users" x:Name="Users"
ItemsSource="{Binding Users.Items}" ItemsSource="{Binding Users.Items}"
DisplayMemberPath="UserName" DisplayMemberPath="UserName"
SelectedIndex="{Binding Users.SelectedIndex, Mode=TwoWay}" TextMemberPath="UserName"
PlaceholderText="Users" PlaceholderText="Users"
IsTextSearchEnabled="True"
Margin="5,0,5,0" Margin="5,0,5,0"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/> HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
<ComboBox <ComboBox

View File

@ -22,7 +22,7 @@ namespace PCUT.Pages
private async void Page_Loaded(object sender, RoutedEventArgs e) private async void Page_Loaded(object sender, RoutedEventArgs e)
{ {
ViewModels.Types.Bind(Types); ViewModels.Types.Bind(Types);
ViewModels.Users.Bind(Users); ViewModels.Users.Bind(Users, user => user.UserName);
await ViewModels.LoadUsersAsync(); await ViewModels.LoadUsersAsync();
} }

View File

@ -18,7 +18,7 @@ namespace PCUT.ViewModels
public class LogViewModel : NotificationBase public class LogViewModel : NotificationBase
{ {
public PaginationViewModel Pagination { get; } = new PaginationViewModel(withSearch: false); public PaginationViewModel Pagination { get; } = new PaginationViewModel(withSearch: false);
public SelectableCollection<UsersModel> Users { get; set; } = new SelectableCollection<UsersModel>(new UsersModel { UserName = "-None-" }); public SelectableCollection<UsersModel> Users { get; set; } = new SelectableCollection<UsersModel>();
public SelectableCollection<string> Types { get; set; } = new SelectableCollection<string>("-None-", new string[] { "login", "logout", "download", "cut" }); public SelectableCollection<string> Types { get; set; } = new SelectableCollection<string>("-None-", new string[] { "login", "logout", "download", "cut" });
public ObservableCollection<Log> Logs { get; } public ObservableCollection<Log> Logs { get; }