One way of dealing with large comboboxes is filtering. Another technique is proposing only the most popular items in the default list, and provide a hyperlink to the full list:
If the hyperlink is clicked, the ComboBox is entirely populated, but by adding non-selectable items you can still make the distinction:
Here's the full code for the demo:
XAML
<Window x:Class="DockOfTheBay.SuggestionComboBoxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DockOfTheBay"
Title="Suggestion ComboBox"
Height="120" Width="300">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Top"
Margin="10 10">
<TextBlock Text="Select: "
Padding="4 3"/>
<ComboBox
x:Name="SuggestionComboBox1"
Padding="4 3"
MinWidth="200"/>
</StackPanel>
</Window>
C#
namespace DockOfTheBay
{
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
/// <summary>
/// Demonstration of using non-selectable items and hyperlinks in a
/// WPF ComboBox.
/// </summary>
public partial class SuggestionComboBoxSample : Window
{
/// <summary>
/// The hyperlink displayed after the the ComboBox's Suggestions.
/// </summary>
private ComboBoxItem linkItem;
/// <summary>
/// Initializes a new instance of the SuggestionComboBoxSample class.
/// </summary>
public SuggestionComboBoxSample()
{
InitializeComponent();
// Add an item that looks like a title
ComboBoxItem item = new ComboBoxItem();
item.Content = "Most Frequent";
item.IsEnabled = false;
item.Background = Brushes.Blue;
item.Foreground = Brushes.White;
SuggestionComboBox1.Items.Add(item);
// Add suggestions
foreach (var name in this.Suggestions())
{
SuggestionComboBox1.Items.Add(name);
}
// Don't add content directly, like the following:
// SuggestionComboBox1.Items.Add(new Separator());
// It will not display properly when databinding is used.
item = new ComboBoxItem();
item.Content = new Separator();
SuggestionComboBox1.Items.Add(item);
Hyperlink link = new Hyperlink();
// 'RequestNavigate' is not fired, so use 'Click' instead
link.Click += this.Link_Click;
link.Inlines.Add(new Run("Show Everything"));
item = new ComboBoxItem();
item.Content = link;
this.linkItem = item;
SuggestionComboBox1.Items.Add(item);
}
/// <summary>
/// Fetches the remaining items, and adds them to the ComboBox.
/// </summary>
/// <param name="sender">The HyperLink.</param>
/// <param name="e">The Event Arg.</param>
private void Link_Click(object sender, RoutedEventArgs e)
{
// Remove Hyperlink
SuggestionComboBox1.Items.Remove(this.linkItem);
// Add an item that looks like a title
ComboBoxItem item = new ComboBoxItem();
item.Content = "The Rest";
item.IsEnabled = false;
item.Background = Brushes.Blue;
item.Foreground = Brushes.White;
SuggestionComboBox1.Items.Add(item);
// Add suggestions
foreach (var name in this.Rest())
{
SuggestionComboBox1.Items.Add(name);
}
}
/// <summary>
/// The Suggested Items.
/// </summary>
/// <returns>A list of Suggestions.</returns>
private List<string> Suggestions()
{
List<string> names = new List<string>();
names.Add("WPF rocks");
names.Add("WCF rocks");
names.Add("XAML is fun");
return names;
}
/// <summary>
/// The non-Suggested Items.
/// </summary>
/// <returns>A list of non-Suggestions.</returns>
private List<string> Rest()
{
List<string> names = new List<string>();
names.Add("WPF rules");
names.Add("WCF rules");
names.Add("WinForms not");
return names;
}
}
}
Here's how the control looks like in a real-life application for cancer registration. It presents a list of the most probable histologic diagnoses, based on key words in the tumor location:
This is not the correct method of doing this. The CollectionViewSource has built in grouping functionality that should be used instead.
ReplyDelete