2012-03-14 18 views
5

ユーザーがコンボボックスから値を選択すると、値を選択すると「SelectionChanged」イベントが発生し、新しい値が設定されます。ただし、値を変更せずにUIの他の場所(編集したいテキストボックスなど)をクリックすると、クリックする回数が2回になります。最初のクリックはコンボボックスのポップアップを閉じ、次のクリックは最初のクリックでアクティブにしたい要素ですポップアップが閉じられた後にフォーカスを適切に設定する方法コンボボックスを取得する方法

コンボボックスのポップアップが最初のクリックでフォーカスターゲットをハイジャックするのを防ぐにはどうすればよいですか?

私はComboBox_LostFocusイベントを監視しようとしましたが、これは間違ったタイミングで発生します。ユーザーがドロップダウンをクリックし、ポップアップリストが表示されると、ComboBox_LostFocusイベントが発生します。フォーカスが失われています。私はそれを変えるために何もしたくない。ユーザーがクリックしてポップアップが閉じると、ComboBoxはフォーカスを取り戻しません(フォーカスはすべてに失われます)ので、このイベントは役に立たなくなります。

+0

こんにちは@Alain、ここでの問題は、あなたが標準的なコントロールの通常の動作から逸脱しようとしていることです。たとえあなたが説明する方法を行う方が良いと思っても、人々の使い方と矛盾しますほとんどの場合、悪い考えです。 – joshuahealy

+1

ここでの本当の問題は、ユーザーが「コンボボックスのリストを表示した後にUIが応答する前に、2回クリックする必要がある」という苦情があることです。私はちょうどユーザーに戻って、それが仕様であると言えば、彼らは別のデザイナーを見つけるでしょう。 – Alain

+0

だから私はほとんどの場合、私たちはすべての顧客に対処しなければならなかったと言っています...うまくいけば、WPFの達人が助けてくれることを願っています。 – joshuahealy

答えて

5

を私は解決策を見つけたかもしれないと思います。コンボボックスにはDropDownClosedイベントがあります。問題はRoutedEventではないため、コンボボックスのスタイルを作成してEventSetterを介してすべてのイベントを継承することはできません。

を(あなたがエラー'DropDownClosed' must be a RoutedEvent registered with a name that ends with the keyword "Event"を取得する)しかし、LoadedイベントするRoutedEventあるので、我々はスタイルでそれをフックすることができます:今、私たちは常に前に発火するイベントを持っていることを

<Style x:Key="ComboBoxCellStyle" TargetType="ComboBox"> 
    <EventSetter Event="Loaded" Handler="ComboBox_Loaded" /> 
</Style> 

、私は最終的に火災がドロップダウンが閉じていることをイベントへのアクセス権を持っていることを今

private void ComboBox_Loaded(object sender, RoutedEventArgs e) 
{ 
    ((ComboBox)sender).DropDownClosed -= ComboBox_OnDropDownClosed; 
    ((ComboBox)sender).DropDownClosed += new System.EventHandler(ComboBox_OnDropDownClosed); 
} 

:コンボボックスで行われている何かは、私たちが実際に気にイベントにフックすることができます私は、煩わしいComboBoxでフォーカスが終了していることを確認するために必要なアクションを実行できます。私の場合は、以下:

void ComboBox_OnDropDownClosed(object sender, System.EventArgs e) 
{ 
    FrameworkElement visualElement = (FrameworkElement)sender; 

    while(visualElement != null && !(visualElement is DataCell)) 
     visualElement = (FrameworkElement)visualElement.TemplatedParent; 
    if(visualElement is DataCell) 
    { 
     DataCell dataCell = (DataCell)visualElement; 
     dataCell.EndEdit(); 
     if(!(dataCell.ParentRow is InsertionRow)) dataCell.ParentRow.EndEdit(); 
    } 
} 

私は、GridViewコントロールでDataCellのテンプレートとしてコンボボックスを持っていて、ユーザーはコンボボックスは、その後の外でクリックされたオープンなポップさと、この特定の問題は、編集を終了からのDataRowを防止しました。グリッド。

これは、このバグで私の最大の問題でした。このイベントでフォーカスを設定する二次的な問題iffユーザーがクリックしました。ユーザーがタブを押すかエスケープするので、コンボボックスも閉じられている可能性があるので、マウスの位置にフォーカスを合わせるだけでは問題ありません。 DropDownClosedイベントの原因を突き止めるための詳細情報が必要です。おそらく、_Loadedイベントハンドラのルーティングされていないイベントにフックすることを意味します。

2

DropDownClosedイベントがあります:

private void comboBox_DropDownClosed(object sender, EventArgs e) 
{ 
    Point m = Control.MousePosition; 
    Point p = this.PointToClient(m); 
    Control c = this.GetChildAtPoint(p); 
    c.Focus(); 
} 

これは、彼らがクリックしたものは何でもコントロールにフォーカスを設定します。たとえば、TextBoxをクリックすると、キャレットはクリックされた場所ではなく、左に表示されます。他のComboBoxをクリックするとフォーカスが移りますが、ポップアップは表示されません。ただし、必要に応じてこのイベントハンドラのケースに対処できると確信しています。

編集:おっと、あなたはWPFを使用しています!じゃあ心配しないで;これはあなたがWinFormsでやる方法です。ただし、WPFでDropDownClosedイベントが発生しています。

編集2:これはそうです。私はWPFに慣れていないので、どれくらい頑強なのか分かりませんが、たとえばTextBoxに焦点を当てます。これは、MainWindowと呼ばれるウィンドウを持つデフォルトのWPFアプリケーションです。コンボボックスのドロップダウンを閉じると、それがメインウィンドウでないマウスの位置で最上位のフォーカス可能なコントロール焦点を当てます:

private void comboBox_DropDownClosed(object sender, EventArgs e) 
{ 
    Point m = Mouse.GetPosition(this); 
    VisualTreeHelper.HitTest(this, new HitTestFilterCallback(FilterCallback), 
     new HitTestResultCallback(ResultCallback), new PointHitTestParameters(m)); 
} 

private HitTestFilterBehavior FilterCallback(DependencyObject o) 
{ 
    var c = o as Control; 
    if ((c != null) && !(o is MainWindow)) 
    { 
     if (c.Focusable) 
     { 
      c.Focus(); 
      return HitTestFilterBehavior.Stop; 
     } 
    } 
    return HitTestFilterBehavior.Continue; 
} 

private HitTestResultBehavior ResultCallback(HitTestResult r) 
{ 
    return HitTestResultBehavior.Continue; 
} 
+1

努力のためのポイント、真剣に。 – Alain

関連する問題