开发者

Issue with WPF custom control (Multi-Select Combobox)

On code project I found the following: http://www.codeproject.com/KB/WPF/MultiComboBox.aspx

I have integrated the following into a sample application and it seems to be working well. The only issue I have right now is that if I type in the control I would like to be taken to the items that start with those letters the same way a normal combobox or listbox functions.

I have tried adding KeyboardNavigation.DirectionalNavigation="Contained" and TextSearch.TextPath="City" as well as IsTextSearchEnabled="True".

None of these seem to be helping. Any thoughts on how to implement text search f开发者_运维问答unctionality using this control?


The author confirm that the control is build to mimic a ComboBox, but it isn't: you should implement your own custom logic to the automatic selection.

EDIT (a.k.a. even better than a finger in the eye)

With reference to the original code: 1) In the Generic.xaml search the MultiSelectComboBoxReadOnlyTemplate, then look for the ScrollViewer tag: name it as "PART_Scroller".

2) Open the MultiComboBox.cs module then find the OnKeyDown function. Modify as follows:

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.Key == System.Windows.Input.Key.Enter)
        {
            IsDropDownOpen = !IsDropDownOpen;
            e.Handled = true;
        }
        else if (IsDropDownOpen)
        {
            if (e.Key>=Key.A && e.Key<= Key.Z) //make it better!
            {
                var ch = (char)((int)(e.Key-Key.A) + 0x41); //awful!!!
                for (int i = 0, count = this.Items.Count; i < count; i++)
                {
                    var text = string.Format("{0}", this.Items[i]);
                    if (text.StartsWith(new string(ch, 1)))
                    {
                        ListBoxItem listBoxItem = (ListBoxItem)this.ItemContainerGenerator.ContainerFromIndex(i);
                        var scroller = (ScrollViewer)this.GetTemplateChild("PART_Scroller"); //move out in OnApplyTemplate
                        scroller.ScrollToVerticalOffset(i);
                        this.ScrollIntoView(listBoxItem);
                        break;
                    }
                }

            }
        }
        else
            base.OnKeyDown(e);
    }

You should make the key analysis better than the mine, but the road is pretty sunny. NOTE: I didn't tried so much to test, I guess should be OK, at least to give you an help. Cheers Mario

EDIT2: here is how to keeping track of the key pressed within one second. 1) Modify as follows:

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.Key == System.Windows.Input.Key.Enter)
        {
            IsDropDownOpen = !IsDropDownOpen;
            e.Handled = true;
        }
        else if (IsDropDownOpen)
        {
            if (e.Key>=Key.A && e.Key<= Key.Z) //make it better!
            {
                var ch = (char)((int)(e.Key-Key.A) + 0x41); //awful!!!
                this._textSought += ch;
                this._timer.Stop();
                this._timer.Start();

                for (int i = 0, count = this.Items.Count; i < count; i++)
                {
                    var text = string.Format("{0}", this.Items[i]);
                    if (text.StartsWith(this._textSought, StringComparison.InvariantCultureIgnoreCase))
                    {
                        ListBoxItem listBoxItem = (ListBoxItem)this.ItemContainerGenerator.ContainerFromIndex(i);
                        var scroller = (ScrollViewer)this.GetTemplateChild("PART_Scroller"); //move out in OnApplyTemplate
                        scroller.ScrollToVerticalOffset(i);
                        this.ScrollIntoView(listBoxItem);
                        break;
                    }
                }

            }
        }
        else
            base.OnKeyDown(e);
    }

2) add the following to the same class:

    public MultiComboBox()
    {
        this.Loaded += new RoutedEventHandler(MultiComboBox_Loaded);
        this.Unloaded += new RoutedEventHandler(MultiComboBox_Unloaded);
    }

    void MultiComboBox_Loaded(object sender, RoutedEventArgs e)
    {
        this._timer = new DispatcherTimer();
        this._timer.Interval = TimeSpan.FromMilliseconds(1000);
        this._timer.Tick += new EventHandler(_timer_Tick);
    }

    void MultiComboBox_Unloaded(object sender, RoutedEventArgs e)
    {
        if (this._timer != null)
        {
            this._timer.Stop();
            this._timer = null;
        }
    }

    void _timer_Tick(object sender, EventArgs e)
    {
        this._timer.Stop();
        this._textSought = string.Empty;
    }

    private DispatcherTimer _timer;
    private string _textSought = string.Empty;

Hope it helps. Cheers Mario

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜