2016-12-20 3 views
1

このスクリーンショットはアプリケーションから取得しました。起こっていることを説明するために、有効なアイテムがリストから選択されていないときに、メッセージボックスを表示するためにleaveイベントを使用しています。現在、入力を開始してマウスで項目を選択しようとすると表示されますが、矢印キーを使用すると表示されません。たとえば。このスクリーンショットでは "cen"と入力し、リストから "Camp Chicken Broth 10.5oz(17960)"を選択したい場合は、方向キーを使用してEnterキーを押しても問題ありませんが、マウスを使用するとMessageBoxの下のイベントが発生します。私はそれがMessageBoxが閉じられた後マウスの左クリックによって選択を可能にすることにも気づいています。ユーザーがMessageBoxを閉じた後でアイテムを選択するのはかなり面倒です。このための回避策はありますか?リーブイベント機能suggestComboBoxマウスではイベントが発生したままにします。方向キーではクリックしません

using System.Windows.Forms; 

namespace AutoCompleteComboBox 
{ 
public class SuggestComboBox : ComboBox 
{ 
    #region fields and properties 

    private readonly ListBox _suggLb = new ListBox { Visible = false, TabStop = false }; 
    private readonly BindingList<string> _suggBindingList = new BindingList<string>(); 
    private Expression<Func<ObjectCollection, IEnumerable<string>>> _propertySelector; 
    private Func<ObjectCollection, IEnumerable<string>> _propertySelectorCompiled; 
    private Expression<Func<string, string, bool>> _filterRule; 
    private Func<string, bool> _filterRuleCompiled; 
    private Expression<Func<string, string>> _suggestListOrderRule; 
    private Func<string, string> _suggestListOrderRuleCompiled; 

    public int SuggestBoxHeight 
    { 
     get { return _suggLb.Height; } 
     set { if (value > 0) _suggLb.Height = value; } 
    } 

    /// <summary> 
    /// If the item-type of the ComboBox is not string, 
    /// you can set here which property should be used 
    /// </summary> 
    public Expression<Func<ObjectCollection, IEnumerable<string>>> PropertySelector 
    { 
     get { return _propertySelector; } 
     set 
     { 
      if (value == null) return; 
      _propertySelector = value; 
      _propertySelectorCompiled = value.Compile(); 
     } 
    } 

    ///<summary> 
    /// Lambda-Expression to determine the suggested items 
    /// (as Expression here because simple lamda (func) is not serializable) 
    /// <para>default: case-insensitive contains search</para> 
    /// <para>1st string: list item</para> 
    /// <para>2nd string: typed text</para> 
    ///</summary> 
    public Expression<Func<string, string, bool>> FilterRule 
    { 
     get { return _filterRule; } 
     set 
     { 
      if (value == null) return; 
      _filterRule = value; 
      _filterRuleCompiled = item => value.Compile()(item, Text); 
     } 
    } 

    ///<summary> 
    /// Lambda-Expression to order the suggested items 
    /// (as Expression here because simple lamda (func) is not serializable) 
    /// <para>default: alphabetic ordering</para> 
    ///</summary> 
    public Expression<Func<string, string>> SuggestListOrderRule 
    { 
     get { return _suggestListOrderRule; } 
     set 
     { 
      if (value == null) return; 
      _suggestListOrderRule = value; 
      _suggestListOrderRuleCompiled = value.Compile(); 
     } 
    } 

    #endregion 

    /// <summary> 
    /// ctor 
    /// </summary> 
    public SuggestComboBox() 
    { 
     // set the standard rules: 
     _filterRuleCompiled = s => s.ToLower().Contains(Text.Trim().ToLower()); 
     _suggestListOrderRuleCompiled = s => s; 
     _propertySelectorCompiled = collection => collection.Cast<string>(); 

     _suggLb.DataSource = _suggBindingList; 
     _suggLb.Click += SuggLbOnClick; 

     ParentChanged += OnParentChanged; 
    } 

    /// <summary> 
    /// the magic happens here ;-) 
    /// </summary> 
    /// <param name="e"></param> 
    protected override void OnTextChanged(EventArgs e) 
    { 
     base.OnTextChanged(e); 

     if (!Focused) return; 

     _suggBindingList.Clear(); 
     _suggBindingList.RaiseListChangedEvents = false; 
     _propertySelectorCompiled(Items) 
      .Where(_filterRuleCompiled) 
      .OrderBy(_suggestListOrderRuleCompiled) 
      .ToList() 
      .ForEach(_suggBindingList.Add); 
     _suggBindingList.RaiseListChangedEvents = true; 
     _suggBindingList.ResetBindings(); 

     _suggLb.Visible = _suggBindingList.Any(); 

     if (_suggBindingList.Count == 1 && 
        _suggBindingList.Single().Length == Text.Trim().Length) 
     { 
      Text = _suggBindingList.Single(); 
      Select(0, Text.Length); 
      _suggLb.Visible = false; 
     } 
    } 

    #region size and position of suggest box 

    /// <summary> 
    /// suggest-ListBox is added to parent control 
    /// (in ctor parent isn't already assigned) 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void OnParentChanged(object sender, EventArgs e) 
    { 
     Parent.Controls.Add(_suggLb); 
     Parent.Controls.SetChildIndex(_suggLb, 0); 
     _suggLb.Top = Top + Height - 3; 
     _suggLb.Left = Left + 3; 
     _suggLb.Width = Width - 20; 
     _suggLb.Font = new Font("Segoe UI", 9); 
    } 

    protected override void OnLocationChanged(EventArgs e) 
    { 
     base.OnLocationChanged(e); 
     _suggLb.Top = Top + Height - 3; 
     _suggLb.Left = Left + 3; 
    } 

    protected override void OnSizeChanged(EventArgs e) 
    { 
     base.OnSizeChanged(e); 
     _suggLb.Width = Width - 20; 
    } 

    #endregion 

    #region visibility of suggest box 

    protected override void OnLostFocus(EventArgs e) 
    { 
     // _suggLb can only getting focused by clicking (because TabStop is off) 
     // --> click-eventhandler 'SuggLbOnClick' is called 
     if (!_suggLb.Focused) 
      HideSuggBox(); 
     base.OnLostFocus(e); 
    } 

    private void SuggLbOnClick(object sender, EventArgs eventArgs) 
    { 
     Text = _suggLb.Text; 
     Focus(); 
    } 

    private void HideSuggBox() 
    { 
     _suggLb.Visible = false; 
    } 

    protected override void OnDropDown(EventArgs e) 
    { 
     HideSuggBox(); 
     base.OnDropDown(e); 
    } 

    #endregion 

    #region keystroke events 

    /// <summary> 
    /// if the suggest-ListBox is visible some keystrokes 
    /// should behave in a custom way 
    /// </summary> 
    /// <param name="e"></param> 
    protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) 
    { 
     if (!_suggLb.Visible) 
     { 
      base.OnPreviewKeyDown(e); 
      return; 
     } 

     switch (e.KeyCode) 
     { 
      case Keys.Down: 
       if (_suggLb.SelectedIndex < _suggBindingList.Count - 1) 
        _suggLb.SelectedIndex++; 
       return; 
      case Keys.Up: 
       if (_suggLb.SelectedIndex > 0) 
        _suggLb.SelectedIndex--; 
       return; 
      case Keys.Enter: 
       Text = _suggLb.Text; 
       Select(0, Text.Length); 
       _suggLb.Visible = false; 
       return; 
      case Keys.Escape: 
       HideSuggBox(); 
       return; 
     } 

     base.OnPreviewKeyDown(e); 
    } 

    private static readonly Keys[] KeysToHandle = new[] { Keys.Down, Keys.Up, Keys.Enter, Keys.Escape }; 
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     // the keysstrokes of our interest should not be processed be base class: 
     if (_suggLb.Visible && KeysToHandle.Contains(keyData)) 
      return true; 
     return base.ProcessCmdKey(ref msg, keyData); 
    } 

    #endregion 
} 

}

+0

はTextChangedを試すか、代わりに休職 –

+0

のSelectedValueChangedしかし、私はそれらを使用している場合、彼らは私もやりたいではないでしょう。それを削除し、私の問題を解決し、このにそれを変更する理由は全くわかりません。 @RobertoPegoraroというコンボボックスのリストに一致するものが見つからないときにMessageBoxを発生させたい – Jevon

+0

Leave以外のイベントを使用していますか?私はここであなたのエラーを再現できなかったので、 –

答えて

0

オーケーで更新

private void suggestComboBox1_Leave(object sender, EventArgs e) 
    { 
     ComboBox c_med = (ComboBox)sender; 
     if (!suggestComboBox1.Items.Contains(c_med.Text)) 
     { 
      MessageBox.Show("Not a valid Cari-med Item!"); 
     } 
    } 

ある画像の下には、私は私のステップとすべてをたどり、私は私のクエリを変更した覚えとそれ以来、私は問題を抱え始めた。

void fillCari()//fill Cari-med dropdown with values 
    { 
     try 
     { 

      string connectionString = "Data Source=CMDLAP126;Initial Catalog=Carimed_Inventory;User ID = sa; Password = 123456;"; 
      SqlConnection con2 = new SqlConnection(connectionString); 
      con2.Open(); 
      string query = "SELECT DISTINCT Item_Description FROM dbo.Carimed"; 
      SqlCommand cmd2 = new SqlCommand(query, con2); 

      SqlDataReader dr2 = cmd2.ExecuteReader(); 
      while (dr2.Read()) 
      { 
       string cari_des = dr2.GetString(dr2.GetOrdinal("Item_Description")); 
       suggestComboBox1.Items.Add(cari_des); 
       suggestComboBox1.Text.Trim(); 
      } 
      //con2.Close(); 
     } 
     catch (Exception ex) 
     { 

      MessageBox.Show(ex.ToString()); 
     } 

この特定の行が問題だった:もともとこれは、数値を上記のコンボボックスを埋め関数であった「DISTINCT」

string query = "SELECT DISTINCT Item_Description FROM dbo.Carimed"; 

が判明、それはとは何かを持っているが

string query = "SELECT Item_Description FROM dbo.Carimed"; 
関連する問題