Searchable ComboBox for Windows Universal Apps

Continuing in search for a searchable ComboBox, I decided to build upon the Searchable ListView created in a previous post.

I know, I know that we should favor composition over inheritance but in this case, I will like this searchable ComboBox to carry over all of the behavior from the current ComboBox implementation without requiring to implement the adapter pattern.

This time, I decided to create a custom XAML control so that I can include the custom style in the resources collection of this custom control.  This searchable ComboBox called a ComboPicker, for lack of a better name is represented using the followng XAML:


<local:ListPicker
x:Class="WinUniversalCustomControls.ComboPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUniversalCustomControls">
<local:ListPicker.Resources>
<Style TargetType="local:ComboPicker">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="IsSwipeEnabled" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True"/>
<Setter Property="ItemContainerTransitions">
<Setter.Value>
<TransitionCollection>
<AddDeleteThemeTransition/>
<ReorderThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="ComboBoxButton"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ListPickerShowButtonVisibility}"
Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ShowListPickerCommand}"
VerticalAlignment="Top" Padding="0">
<TextBox
BorderThickness="0"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Foreground="{ThemeResource ApplicationForegroundThemeBrush}"
PlaceholderText=" choose an item "
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem, Mode=TwoWay}"
Padding="0"
Margin="0"
HorizontalAlignment="Stretch"></TextBox>
</Button>
<Grid Grid.Row="1" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ListPickerVisibility}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<TextBox
Grid.Row="0"
PlaceholderText="search box"
x:Name="FilterTextBox"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FilterText,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<ScrollViewer
Grid.Row="1"
x:Name="ScrollViewer" AutomationProperties.AccessibilityView="Raw" BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}" IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" TabNavigation="{TemplateBinding TabNavigation}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
<ItemsPresenter FooterTransitions="{TemplateBinding FooterTransitions}" FooterTemplate="{TemplateBinding FooterTemplate}" Footer="{TemplateBinding Footer}" HeaderTemplate="{TemplateBinding HeaderTemplate}" Header="{TemplateBinding Header}" HeaderTransitions="{TemplateBinding HeaderTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</ScrollViewer>
</Grid>
</Grid>

</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:ListPicker.Resources>


</local:ListPicker>

The code behind powering this searchable combo box is as follows:


public sealed partial class ComboPicker
{
public ComboPicker()
{
this.InitializeComponent();
ListPickerVisibility = Visibility.Collapsed;
ShowListPickerCommand = new RelayCommand((() =>
{
ListPickerVisibility = Visibility.Visible;
ListPickerShowButtonVisibility = Visibility.Collapsed;
}));
SelectionChanged += OnSelectionChanged;
}

public static readonly DependencyProperty ListPickerShowButtonVisibilityProperty = DependencyProperty.Register(
"ListPickerShowButtonVisibility",
typeof(Visibility),
typeof(ComboPicker),
new PropertyMetadata(Windows.UI.Xaml.Visibility.Visible, (o, args) =>
{
((ComboPicker)o).OnListPickerShowButtonVisibilityChanged((Visibility)args.NewValue);
}));

private void OnListPickerShowButtonVisibilityChanged(Visibility newValue)
{
}

public Visibility ListPickerShowButtonVisibility
{
get { return (Visibility)GetValue(ListPickerShowButtonVisibilityProperty); }
set { SetValue(ListPickerShowButtonVisibilityProperty, value); }
}

public static readonly DependencyProperty ListPickerVisibilityProperty = DependencyProperty.Register(
"ListPickerVisibility",
typeof(Visibility),
typeof(ComboPicker),
new PropertyMetadata(Windows.UI.Xaml.Visibility.Collapsed, (o, args) =>
{
((ComboPicker)o).OnListPickerVisibilityChanged((Visibility)args.NewValue);
}));

public Visibility ListPickerVisibility
{
get { return (Visibility)GetValue(ListPickerVisibilityProperty); }
set { SetValue(ListPickerVisibilityProperty, value); }
}

public static readonly DependencyProperty ShowListPickerCommandProperty = DependencyProperty.Register(
"ShowListPickerCommand",
typeof(ICommand),
typeof(ComboPicker),
new PropertyMetadata(null, null));

public ICommand ShowListPickerCommand
{
get { return (ICommand)GetValue(ShowListPickerCommandProperty); }
set { SetValue(ShowListPickerCommandProperty, value); }
}
private void OnListPickerVisibilityChanged(Visibility visibility)
{

}

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListPickerVisibility = Visibility.Collapsed;
ListPickerShowButtonVisibility = Visibility.Visible;
}
}

All I am doing is using a button and displaying the ListPicker when a user clicks on it to select an item.  When the user has selected an item, the button’s content, which is a textbox is updated accordingly.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s