Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF可编辑组合框慢速键入_Wpf_Performance_Combobox - Fatal编程技术网

WPF可编辑组合框慢速键入

WPF可编辑组合框慢速键入,wpf,performance,combobox,Wpf,Performance,Combobox,我有一个WPF组合框,如下所示: 如果我在绑定到位(MVVM)时单击可编辑组合以使其具有焦点,然后按住任意键,我假设组合将很快被该键填充,但事实并非如此。 如果我删除displaymemberpath,然后执行相同的操作,那么我就有了预期的行为。当然我真的需要装订 只有当组合有很多元素时,性能惩罚才会显示。我的元素有6000个 我不明白这场比赛的点球是从哪里来的。有没有办法绕过这个问题?下面的代码通过创建一个专门的组合框来解决问题,该组合框基本上缓存了所有绑定结果。我通过使用.NET refl

我有一个WPF组合框,如下所示:

如果我在绑定到位(MVVM)时单击可编辑组合以使其具有焦点,然后按住任意键,我假设组合将很快被该键填充,但事实并非如此。 如果我删除displaymemberpath,然后执行相同的操作,那么我就有了预期的行为。当然我真的需要装订

只有当组合有很多元素时,性能惩罚才会显示。我的元素有6000个


我不明白这场比赛的点球是从哪里来的。有没有办法绕过这个问题?

下面的代码通过创建一个专门的组合框来解决问题,该组合框基本上缓存了所有绑定结果。我通过使用.NET reflector查看combobox和itemscontrol的原始源代码创建了它

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Controls.Primitives;
using System.Collections;

namespace ICeTechControlLibrary
{
    public class FastEditComboBox : ComboBox
    {
        //PARTS
        private TextBox _TextBoxPart = null;

        //DEPENDENCY PROPERTIES
        public static readonly DependencyProperty TextProperty
            = DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(FastEditComboBox.OnTextChanged)));

        private List<string> _CompletionStrings = new List<string>();
        private int _textBoxSelectionStart;
        private bool _updatingText;
        private bool _updatingSelectedItem;
        private static Dictionary<TextBox, FastEditComboBox> _TextBoxDictionary = new Dictionary<TextBox,FastEditComboBox>();

        static FastEditComboBox()
        {
            EventManager.RegisterClassHandler(typeof(TextBox), TextBox.TextChangedEvent, new TextChangedEventHandler(FastEditComboBox.OnTextChanged));
            EventManager.RegisterClassHandler(typeof(TextBox), TextBox.SelectionChangedEvent, new RoutedEventHandler(FastEditComboBox.OnSelectionChanged));
        }

        public string Text
        {
            get
            {
                return (string)base.GetValue(TextProperty);
            }
            set
            {
                base.SetValue(TextProperty, value);
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _TextBoxPart = base.GetTemplateChild("PART_EditableTextBox") as TextBox;
            if (!_TextBoxDictionary.ContainsKey(_TextBoxPart)) _TextBoxDictionary.Add(_TextBoxPart, this);
        }

        private void OnTextBoxSelectionChanged(object sender, RoutedEventArgs e)
        {
            this._textBoxSelectionStart = this._TextBoxPart.SelectionStart;
        }

        private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e)
        {
            if (IsEditable)
            {
                TextUpdated(_TextBoxPart.Text, true);
            }
        }

        private void TextUpdated(string newText, bool textBoxUpdated)
        {
            if (!_updatingText && !_updatingSelectedItem)
            {
                try
                {
                    _updatingText = true;
                    if (base.IsTextSearchEnabled)
                    {
                        int num = FindMatchingPrefix(newText);
                        if (num >= 0)
                        {
                            if (textBoxUpdated)
                            {
                                int selectionStart = this._TextBoxPart.SelectionStart;
                                if ((selectionStart == newText.Length) && (selectionStart > this._textBoxSelectionStart))
                                {
                                    string primaryTextFromItem = _CompletionStrings[num];
                                    this._TextBoxPart.Text = primaryTextFromItem;
                                    this._TextBoxPart.SelectionStart = newText.Length;
                                    this._TextBoxPart.SelectionLength = primaryTextFromItem.Length - newText.Length;
                                    newText = primaryTextFromItem;
                                }
                            }
                            else
                            {
                                string b = _CompletionStrings[num];
                                if (!string.Equals(newText, b, StringComparison.CurrentCulture))
                                {
                                    num = -1;
                                }
                            }
                        }
                        if (num != base.SelectedIndex)
                        {
                            SelectedIndex = num;
                        }
                    }
                    if (textBoxUpdated)
                    {
                        Text = newText;
                    }
                    else if (_TextBoxPart != null)
                    {
                        _TextBoxPart.Text = newText;
                    }
                }
                finally
                {
                    _updatingText = false;
                }
            }
        }

        internal void SelectedItemUpdated()
        {
            try
            {
                this._updatingSelectedItem = true;
                if (!this._updatingText)
                {
                    string primaryTextFromItem = GetPrimaryTextFromItem(SelectedItem);
                    Text = primaryTextFromItem;
                }
                this.Update();
            }
            finally
            {
                this._updatingSelectedItem = false;
            }
        }

        private void Update()
        {
            if (this.IsEditable)
            {
                this.UpdateEditableTextBox();
            }
            else
            {
                //this.UpdateSelectionBoxItem();
            }
        }

        private void UpdateEditableTextBox()
        {
            if (!_updatingText)
            {
                try
                {
                    this._updatingText = true;
                    string text = this.Text;
                    if ((this._TextBoxPart != null) && (this._TextBoxPart.Text != text))
                    {
                        this._TextBoxPart.Text = text;
                        this._TextBoxPart.SelectAll();
                    }
                }
                finally
                {
                    this._updatingText = false;
                }
            }
        }

        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.RaiseEvent(e);
            this.SelectedItemUpdated();
            if (this.IsDropDownOpen)
            {
                object Item = SelectedItem;
                if (Item != null)
                {
                    base.OnSelectionChanged(e);
                }
                //object internalSelectedItem = base.InternalSelectedItem;
                //if (internalSelectedItem != null)
                //{
                //    base.NavigateToItem(internalSelectedItem, ItemsControl.ItemNavigateArgs.Empty);
                //}
            }
        }

        int FindMatchingPrefix(string s)
        {
            int index = _CompletionStrings.BinarySearch(s, StringComparer.OrdinalIgnoreCase);
            if (index >= 0) return index;
            index = ~index;
            string p = _CompletionStrings[index];
            if (p.StartsWith(s, StringComparison.CurrentCultureIgnoreCase)) return index;
            return -1;
        }

        protected override void OnDisplayMemberPathChanged(string oldDisplayMemberPath, string newDisplayMemberPath)
        {
            FillCompletionStrings();
        }

        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    AddCompletionStrings(e.NewItems);
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    RemoveCompletionStrings(e.OldItems);
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    FillCompletionStrings();
                    break;
            }
        }

        private void FillCompletionStrings()
        {
            _CompletionStrings.Clear();
            AddCompletionStrings(Items);
        }

        private void RemoveCompletionStrings(IList items)
        {
            foreach (object o in items)
            {
                RemoveCompletionStringForItem(o);
            }
        }

        private void AddCompletionStrings(IList items)
        {
            foreach (object o in items)
            {
                AddCompletionStringForItem(o);
            }
        }

        private void AddCompletionStringForItem(object item)
        {
            Binding binding = new Binding(DisplayMemberPath);
            TextBlock tb = new TextBlock();
            tb.DataContext = item;
            tb.SetBinding(TextBlock.TextProperty, binding);
            string s = tb.Text;
            int index = _CompletionStrings.BinarySearch(s, StringComparer.OrdinalIgnoreCase);
            if (index < 0)
            {
                _CompletionStrings.Insert(~index, s);
            }
            else
            {
                _CompletionStrings.Insert(index, s);
            }
        }

        private string GetPrimaryTextFromItem(object item)
        {
            Binding binding = new Binding(DisplayMemberPath);
            TextBlock tb = new TextBlock();
            tb.DataContext = item;
            tb.SetBinding(TextBlock.TextProperty, binding);
            string s = tb.Text;
            return s;
        }

        private void RemoveCompletionStringForItem(object item)
        {
            Binding binding = new Binding(DisplayMemberPath);
            TextBlock tb = new TextBlock();
            tb.DataContext = item;
            tb.SetBinding(TextBlock.TextProperty, binding);
            string s = tb.Text;
            int index = _CompletionStrings.BinarySearch(s, StringComparer.OrdinalIgnoreCase);
            if (index >= 0) _CompletionStrings.RemoveAt(index);
        }

        private static void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox tb = e.Source as TextBox;
            if (tb.Name == "PART_EditableTextBox")
            {
                if (_TextBoxDictionary.ContainsKey(tb))
                {
                    FastEditComboBox combo = _TextBoxDictionary[tb];
                    combo.OnTextBoxTextChanged(sender, e);
                    e.Handled = true;
                }
            }
        }

        private static void OnSelectionChanged(object sender, RoutedEventArgs e)
        {
            TextBox tb = e.Source as TextBox;
            if (tb.Name == "PART_EditableTextBox")
            {
                if (_TextBoxDictionary.ContainsKey(tb))
                {
                    FastEditComboBox combo = _TextBoxDictionary[tb];
                    combo.OnTextBoxSelectionChanged(sender, e);
                    e.Handled = true;
                }
            }
        }

        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FastEditComboBox actb = (FastEditComboBox)d;
            actb.TextUpdated((string)e.NewValue, false);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
运用系统反思;
使用系统组件模型;
使用System.Collections.ObjectModel;
使用System.Windows.Controls.Primitives;
使用系统集合;
命名空间ICeTechControlLibrary
{
公共类FastEditComboBox:ComboBox
{
//零件
私有文本框_TextBoxPart=null;
//依赖属性
公共静态只读DependencyProperty TextProperty
=DependencyProperty.Register(“Text”、typeof(string)、typeof(AutoCompleteTextBox)、new FrameworkPropertyMetadata(string.Empty、FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.Bindstwoway默认情况下,new PropertyChangedCallback(FastEditComboBox.OnTextChanged));
私有列表_CompletionStrings=新列表();
专用int_文本框选择启动;
私有bool\u更新文本;
私有bool\u更新selecteditem;
私有静态字典_TextBoxDictionary=新字典();
静态FastEditComboBox()
{
RegisterClassHandler(typeof(TextBox)、TextBox.TextChangedEvent、newtextchangedeventhandler(fastedicombobox.OnTextChanged));
EventManager.RegisterClassHandler(typeof(TextBox)、TextBox.SelectionChangedEvent、new RoutedEventHandler(fastedComboBox.OnSelectionChanged));
}
公共字符串文本
{
得到
{
返回(字符串)base.GetValue(TextProperty);
}
设置
{
base.SetValue(TextProperty,value);
}
}
应用程序模板()上的公共重写无效
{
base.OnApplyTemplate();
_TextBoxPart=base.GetTemplateChild(“PART\u EditableTextBox”)作为文本框;
如果(!\u TextBoxDictionary.ContainsKey(\u TextBoxPart))\u TextBoxDictionary.Add(\u TextBoxPart,this);
}
private void OnTextBoxSelectionChanged(对象发送方,路由目标)
{
this.\u textBoxSelectionStart=this.\u TextBoxPart.SelectionStart;
}
私有void OnTextBoxTextChanged(对象发送方,textchangedventargs e)
{
如果(可编辑)
{
TextUpdated(_TextBoxPart.Text,true);
}
}
私有无效文本更新(字符串newText,bool textBoxUpdated)
{
if(!\u updateText&!\u updateingselecteditem)
{
尝试
{
_updateText=true;
if(base.IsTextSearchEnabled)
{
int num=FindMatchingPrefix(新文本);
如果(num>=0)
{
如果(TextBoxUpdate)
{
int-selectionStart=这个;
如果((selectionStart==newText.Length)和&(selectionStart>this.\u文本框selectionStart))
{
字符串primaryTextFromItem=_CompletionStrings[num];
此._TextBoxPart.Text=primaryTextFromItem;
这是._TextBoxPart.SelectionStart=newText.Length;
此.u TextBoxPart.SelectionLength=primaryTextFromItem.Length-newText.Length;
newText=primaryTextFromItem;
}
}
其他的
{
字符串b=_CompletionStrings[num];
如果(!string.Equals(newText,b,StringComparison.CurrentCulture))
{
num=-1;
}
}
}
if(num!=base.SelectedIndex)
{
SelectedIndex=num;
}
}
如果(TextBoxUpdate)
{
文本=新文本;
}
else if(_TextBoxPart!=null)
{
_Text=newText;
}
}
最后
{
_updateText=false;
}
}
}
内部void SelectedItemUpdated()
{
尝试
{
这是.\u updatenselecteditem=true;
如果(!this.\u updateingtext)
{
字符串primaryTextFromItem=GetPrimaryTextFromItem(SelectedItem);