2013-01-14 34 views
5

Tôi đang sử dụng ComboBox để chèn mẫu văn bản vào điều khiển RichEdit (tên của mẫu nằm trong danh sách chọn cho ComboBox.)Làm cách nào để biết khi nào giá trị được "chọn lại" trong ComboBox?

Tất cả đều hoạt động tốt trừ khi người dùng chọn cùng một giá trị trong danh sách lần nữa. Sau đó, SelectionChanged không kích hoạt. Điều đó có ý nghĩa dựa trên tên của sự kiện (Lựa chọn Thay đổi), nhưng tôi cần biết rằng giá trị đã được chọn lại để tôi có thể chèn lại.

Có cách nào để biết rằng một mục đã được chọn lại từ ComboBox không? (Hoặc kiểm soát tốt hơn để sử dụng?)

Tôi đã thử sử dụng sự kiện DropDownClosed, nhưng điều đó sẽ kích hoạt ngay cả khi mục không được chọn lại. (Họ mở trình đơn thả xuống rồi nhấp vào một điều khiển khác.)

+0

Sau khi chèn u thay đổi chỉ mục đã chọn thành -1 – Paparazzi

Trả lời

1

Bạn cần cung cấp một số mã để hiển thị những gì bạn đang cố gắng làm. Nếu một mục đã được chọn, tại sao mẫu của kiểm soát RichEdit chưa được đặt?
Khi giao dịch với WPF, nó giúp làm quen với việc ràng buộc để xem các mô hình, không chỉ cho những thứ như ItemsSource mà còn là SelectedItem. Với kịch bản mà bạn mô tả, tôi sẽ sử dụng một ràng buộc cho SelectedItem cho Mô hình Xem sau đó liên kết mẫu kiểm soát của RichEdit với cùng một thuộc tính Chế độ xem, sử dụng trình chuyển đổi giá trị nếu cần. Bằng cách này, bạn không cần phải lộn xộn xung quanh với các sự kiện nhấp chuột và tương tự. Với điều kiện thuộc tính Chế độ xem là DependencyProperty hoặc kích hoạt sự kiện PropertyChanged (xem INotifyPropertyChanged) mẫu kiểm soát RichEdit của bạn sẽ tự động phản ánh lựa chọn trong trình đơn thả xuống.

** Chỉnh sửa ** Dựa trên nhận xét của bạn Tôi cho rằng hành vi bạn muốn là đặt văn bản dựa trên lựa chọn kết hợp nhưng cho phép người dùng tùy chỉnh văn bản đó. Tuy nhiên, nếu chỉnh sửa, họ có thể chọn lại giá trị kết hợp để đặt lại văn bản. Vấn đề là nếu mục đã được chọn thì không có sự kiện nào được kích hoạt để móc vào. Giải pháp là nếu nội dung văn bản thay đổi, điều này sẽ bỏ chọn bất kỳ lựa chọn kết hợp nào (vì combo không còn phản ánh nội dung của hộp văn bản nữa.) Các ràng buộc có thể quản lý điều này khá độc đáo:

Chế độ xem ví dụ này sử dụng TextBox vì đơn giản:

<Window x:Class="UISample.UITemplateSample" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="UITemplateSample" Height="300" Width="300"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="auto"/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 

    <ComboBox ItemsSource="{Binding Path=Templates}" SelectedItem="{Binding Path=SelectedTemplate}" DisplayMemberPath="Name"/> 
    <TextBox Grid.Row="1" AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Path=Text}"/> 
</Grid> 

ViewModel:

class TemplateSampleViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public ObservableCollection<TextTemplate> Templates 
    { 
     get; 
     private set; 
    } 

    private TextTemplate _selectedTemplate; 
    public TextTemplate SelectedTemplate 
    { 
     get{ return _selectedTemplate; } 
     set 
     { 
      if (_selectedTemplate == value) 
       return; 
      _selectedTemplate = value; 
      if (_selectedTemplate != null) 
       Text = _selectedTemplate.TemplateText; 
      firePropertyChanged("SelectedTemplate"); 
     } 
    } 

    private string _text; 
    public string Text 
    { 
     get { return _text; } 
     set 
     { 
      if (_text == value) 
       return; 

      _text = value; 
      firePropertyChanged("Text"); 
      var matchingTemplate = Templates.FirstOrDefault(t => t.TemplateText == _text); 
      SelectedTemplate = matchingTemplate; 

     } 
    } 

    public TemplateSampleViewModel(IEnumerable<TextTemplate> templates) 
    { 
     Templates = new ObservableCollection<TextTemplate>(templates); 
    } 

    private void firePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

và dây điện nó lên:

  var viewModel = new TemplateSampleViewModel(new[] 
                 { 
                  new TextTemplate {Name = "First", TemplateText = "This is the first item"}, 
                  new TextTemplate {Name = "Second", TemplateText = "This is the second item"}, 
                  new TextTemplate {Name = "Third", TemplateText = "This is the third item"}, 
                 }); 
     var test = new UITemplateSample {DataContext = viewModel}; 
     test.Show(); 

Điều này liên kết hộp kết hợp, sau đó là mục được chọn, hộp văn bản được cập nhật tự động. Khi nội dung của hộp văn bản thay đổi, mẫu được kiểm tra để xem liệu nó có phù hợp và nếu không, mục kết hợp được bỏ chọn. Nếu mục nhập khớp với mẫu thì mẫu đó sẽ được chọn tự động.

+0

Khi tôi nói "T ext Template "Tôi đã không đề cập đến một mẫu WPF. Tôi có nghĩa là tôi chèn văn bản thực tế (một văn bản được thiết lập sẵn "mẫu") vào RichTextBox. Tôi không thực sự ràng buộc với bất cứ điều gì trên này (ngoài danh sách trong ComboBox). Khi một mục trong combobox được chọn, tôi chèn văn bản vào hộp văn bản có định dạng. Nhưng tôi cần phải chèn nó một lần nữa nếu cùng một mục trong hộp kết hợp được chọn. – Vaccano

+0

Nguyên tắc tương tự cũng được áp dụng. Tôi sẽ cập nhật câu trả lời để phác thảo cách áp dụng ràng buộc. –

1

Điều tốt nhất tôi có thể tìm thấy là xóa giá trị đã chọn khi menu thả xuống mở ra. Điều này không lý tưởng vì người dùng không giữ vị trí trước đó của họ như là một điểm tham chiếu (tốt cho danh sách dài). Nhưng đó là giải pháp tốt nhất tôi có thể tìm thấy.

Đây là mã tôi đã sử dụng:

ctor() 
{ 
    myComboBox.DropDownOpened += OnDropDownOpened; 
} 

private void OnDropDownOpened(object sender, EventArgs e) 
{ 
    var comboBox = ((ComboBox)sender); 
    comboBox.SelectedItem = null; 
} 
2

Nghe có vẻ như cách bạn đang sử dụng combo box của bạn không phù hợp với sử dụng bình thường. Nó sẽ làm việc để có một nút bên cạnh hộp kết hợp chèn mẫu đã chọn. Tôi nghĩ rằng hành vi đó sẽ hoạt động tốt hơn cho những người dùng quen thuộc với hành vi tìm kiếm của Google với các sugestions tìm kiếm

1

Tôi sẽ sử dụng hộp danh sách. Người dùng không cần phải mở nó. Thay vào đó, anh ta có thể ngay lập tức chọn một mục từ danh sách. Ngoài ra tôi sẽ không đính kèm chức năng này vào sự kiện SelectionChanged nhưng sự kiện MouseDoubleClick. Điều này cho phép chọn và chọn lại một mục dễ dàng. Ngoài ra tôi sẽ thêm một nút, kích hoạt chức năng tương tự. Nhấp đúp chỉ nên là một loại phím tắt cho nút này, nút cũng có thể có văn bản mô tả và/hoặc biểu tượng, làm cho nó trực quan hơn.

SelectionChanged sẽ kích hoạt ngay cả khi người dùng di chuyển lên và xuống bằng các phím mũi tên, nhưng chức năng sẽ không được kích hoạt sau đó.

2

Tôi có cùng một câu hỏi và cuối cùng tôi đã tìm thấy câu trả lời:

Bạn cần phải xử lý cả hai sự kiện SelectionChanged và DropDownClosed như thế này:

Trong XAML:

<ComboBox Name="cmbSelect" SelectionChanged="ComboBox_SelectionChanged" DropDownClosed="ComboBox_DropDownClosed"> 
    <ComboBoxItem>1</ComboBoxItem> 
    <ComboBoxItem>2</ComboBoxItem> 
    <ComboBoxItem>3</ComboBoxItem> 
</ComboBox> 

Trong C# :

private bool handle = true; 
private void ComboBox_DropDownClosed(object sender, EventArgs e) { 
    if(handle)Handle(); 
    handle = true; 
} 

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { 
    ComboBox cmb = sender as ComboBox; 
    handle = !cmb.IsDropDownOpen; 
    Handle(); 
} 

private void Handle() { 
    switch (cmbSelect.SelectedItem.ToString().Split(new string[] { ": " }, StringSplitOptions.None).Last()) 
    { 
     case "1": 
      //Handle for the first combobox 
      break; 
     case "2": 
      //Handle for the second combobox 
      break; 
     case "3": 
      //Handle for the third combobox 
      break; 
    } 
} 
Các vấn đề liên quan