Robert
Robert

Reputation: 559

Customize Control Template of Silverlight Combobox

I want to implement this in Silverlight.

Combobox with an inline filter in the popup

http://gregandora.wordpress.com/2012/01/25/filtering-items-in-a-wpf-combobox/

Unfortunately it's for WPF and XAML is not compatible. It's very hard to convert it or understand how to change the control template of the combobox.

Any idea?

Upvotes: 1

Views: 1822

Answers (1)

Chui Tey
Chui Tey

Reputation: 5564

Here's a demo of the solution: https://dl.dropbox.com/u/8424800/StackOverflowSl.html (see ComboBox Filter)

I took the default Silverlight ComboBox template and added a "FilterTextBox" to the Popup section. I couldn't post the whole xaml as it exceeded StackOverflow's limit. The full sources are here as a GitHub Gist. I've left in the important parts. Next, the event handlers on the TextBox needs to be hooked up.

<Style TargetType="ComboBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <Grid>                       
                    <Popup x:Name="Popup">
                        <Border x:Name="PopupBorder"
                                Height="Auto"
                                HorizontalAlignment="Stretch"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="3">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <GradientStop Offset="0" Color="#FFFFFFFF" />
                                    <GradientStop Offset="1" Color="#FFFEFEFE" />
                                </LinearGradientBrush>
                            </Border.Background>
                            <Grid>
                                <TextBox x:Name="FilterTextBox"
                                            Height="22"
                                            VerticalAlignment="Top" />
                                <ScrollViewer x:Name="ScrollViewer"
                                                Margin="0,25,0,0"
                                                BorderThickness="0"
                                                Padding="1">
                                    <ItemsPresenter />
                                </ScrollViewer>
                            </Grid>
                        </Border>
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Wiring up the TextBox

public Q12513294()
{
    // Required to initialize variables
    InitializeComponent();

    InitializeMyCombo(
        Enumerable.Range(1, 99).Select(x => "Beer " + x.ToString() + " on the wall"),
        (object item, string filter) => (item as String).Contains(filter)
    );
}

private void InitializeMyCombo(IEnumerable items, Func<object, string, bool> filter)
{
    MyComboBox.Loaded += (s, e) =>
    {
        // PagedCollectionView implements a filterable collection
        PagedCollectionView list = new PagedCollectionView(items);
        MyComboBox.ItemsSource = list;

        // Set the filter based on the contents of the textbox
        TextBox filterTextBox = MyComboBox.GetTemplateChild<TextBox>("FilterTextBox");
        list.Filter = new Predicate<object>(
            item => filter(item, filterTextBox.Text)
            );

        // Refresh the filter each time
        filterTextBox.TextChanged += (s2, e2) =>
        {
            list.Refresh();
            filterTextBox.Focus();
        };
    };

}

public static class Helper
{
    public static T GetTemplateChild<T>(this DependencyObject parent, string partName)
    {
        return (T)(VisualTreeHelper.GetChild(parent, 0) as Panel).FindName(partName);
    }
}

Upvotes: 1

Related Questions