2012-03-14 29 views
5

Khi người dùng chọn giá trị từ combobox, nếu họ chọn giá trị, sự kiện "SelectionChanged" sẽ kích hoạt và giá trị mới được đặt và mọi thứ đều ổn. Tuy nhiên, nếu họ quyết định không thay đổi giá trị và nhấp vào nơi khác trên giao diện người dùng (như hộp văn bản họ muốn chỉnh sửa), họ phải nhấp hai lần - nhấp chuột đầu tiên chỉ cần đóng cửa sổ bật lên combobox và nhấp tiếp theo sẽ tập trung yếu tố họ muốn kích hoạt trên lần nhấp đầu tiên.Làm thế nào để có được một combobox thích hợp đặt tiêu điểm trực tiếp sau khi popup đóng

Làm cách nào để ngăn không cho cửa sổ bật lên combobox chiếm đoạt mục tiêu tiêu điểm trên lần nhấp đầu tiên như vậy?

Tôi đã thử giám sát sự kiện ComboBox_LostFocus, nhưng điều này xảy ra vào thời điểm không đúng. Khi người dùng nhấp vào danh sách thả xuống và danh sách bật lên được hiển thị, sự kiện ComboBox_LostFocus sẽ kích hoạt - nó sẽ mất tập trung vào danh sách thả xuống của riêng nó. Tôi không muốn làm gì để thay đổi điều đó. Khi người dùng sau đó nhấp chuột đi và cửa sổ bật lên đóng lại, ComboBox không bao giờ lấy lại tiêu điểm (tiêu điểm chỉ là 'mất' cho tất cả mọi thứ) và vì vậy sự kiện này là vô ích.

+0

Xin chào @Alain, vấn đề ở đây là bạn đang cố gắng đi chệch khỏi hành vi bình thường của kiểm soát tiêu chuẩn .. Ngay cả khi bạn nghĩ tốt hơn nên làm theo cách bạn mô tả, nó sẽ không phù hợp với cách mọi người được sử dụng để combobox làm việc, mà trong nhiều trường hợp là một ý tưởng tồi. – joshuahealy

+1

Vấn đề thực sự ở đây là người dùng phàn nàn rằng họ "cần phải bấm hai lần trước khi giao diện người dùng phản hồi sau khi xem danh sách combobox". Nếu tôi chỉ trở lại với người dùng và nói với họ rằng đó là do thiết kế, họ sẽ tìm thấy một nhà thiết kế khác. – Alain

+0

Đó là lý do tại sao tôi đã nói trong những trường hợp NHẤT ... như tất cả chúng ta đã phải đối phó với khách hàng trước đây ... Hy vọng rằng một số guru WPF có thể giúp đỡ! – joshuahealy

Trả lời

5

Tôi nghĩ rằng tôi có thể đã tìm thấy một giải pháp. Comboboxes có một sự kiện DropDownClosed - vấn đề là nó không phải là một RoutedEvent, vì vậy bạn không thể tạo ra một phong cách cho ComboBoxes và có tất cả họ kế thừa sự kiện thông qua một EventSetter. (Bạn nhận được lỗi 'DropDownClosed' must be a RoutedEvent registered with a name that ends with the keyword "Event")

Tuy nhiên, Loaded kiện một RoutedEvent, vì vậy chúng tôi có thể móc vào đó theo phong cách:

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

Bây giờ chúng ta có một sự kiện mà sẽ luôn bắn trước bất cứ điều gì khác được thực hiện với các ComboBox, chúng ta có thể móc vào các sự kiện chúng tôi thực sự quan tâm đến:

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

Bây giờ cuối cùng tôi đã được tiếp cận với sự kiện này sẽ kích hoạt khi thả xuống là đóng cửa, Tôi có thể thực hiện bất kỳ hành động nào tôi cần để đảm bảo tiêu điểm được chấm dứt trên ComboBox khó chịu. Trong trường hợp của tôi, sau đây:

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(); 
    } 
} 

Tôi đã có một ComboBox như mẫu của một DataCell trong một GridView, và vấn đề cụ thể này đã được ngăn chặn DataRow từ kết thúc chỉnh sửa khi người dùng bật mở một ComboBox sau đó nhấp bên ngoài Cái lưới sắt.

Đó là vấn đề lớn nhất của tôi với lỗi này.Vấn đề thứ hai đặt trọng tâm trong sự kiện này iff người dùng đã nhấp. Combobox cũng có thể đã bị đóng bởi vì người dùng nhấn tab hoặc thoát, mặc dù vậy chúng tôi không thể chỉ tập trung vào vị trí chuột. Chúng tôi cần thêm thông tin về những gì đã gây ra sự kiện DropDownClosed để kích hoạt. Có lẽ có nghĩa là móc nối vào nhiều sự kiện chưa được sắp xếp trong trình xử lý sự kiện _Loaded.

2

Có một sự kiện 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(); 
} 

này sẽ chỉ đặt trọng tâm vào bất cứ điều gì kiểm soát họ nhấp vào. Nếu họ bấm vào một TextBox, ví dụ, dấu mũ sẽ ở bên trái thay vì nơi họ nhấp vào. Nếu họ nhấp vào một ComboBox khác, nó sẽ tập trung ở đó, nhưng nó sẽ không hiển thị popup của nó. Tuy nhiên, tôi chắc chắn bạn có thể xử lý những trường hợp đó trong trình xử lý sự kiện này nếu bạn cần.

EDIT: Rất tiếc, bạn đang sử dụng WPF! Đừng bận tâm; đây là cách bạn làm điều đó trong WinForms. Tuy nhiên, bạn vẫn có sự kiện DropDownClosed trong WPF.

CHỈNH SỬA 2: Điều này dường như thực hiện. Tôi không quen thuộc với WPF vì vậy tôi không biết nó mạnh mẽ như thế nào, nhưng nó sẽ tập trung vào một TextBox, ví dụ. Đây là một ứng dụng WPF mặc định với Window được gọi là MainWindow. Khi bạn đóng thả xuống của combobox, nó sẽ tập trung vào Control trên hầu hết các thể đặt tiêu điểm ở vị trí chuột mà không được MainWindow:

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

Điểm cho nỗ lực dude, nghiêm túc. – Alain

Các vấn đề liên quan