.NET WinForms ComboBox özdeş öğeler ve Selectedındexchanged olay

oy
5

Bu WinForms .NET uygulaması varken gibi görünüyor ve ( Açılan tarzı ayarlı) bir ComboBox ve bu ComboBox aynıdır içinde birden çok öğe vardır, garip şeyler olur. Özellikle, seçilen öğenin dizini değiştirebilirsiniz olmadan Selectedındexchanged olay ateş.

Tabii ki bu son zamanlarda üzerinde saçımı çekerek şey bu, hangi kitle karışıklık ve tuhaf, anlaşılması güç hatalara neden olur.

Burada ben neden bahsettiğimi görmek için kullanabileceğiniz basit bir örnek:

  • (Ben VB.NET kullanıyorum ancak çevirmek için çekinmeyin - bu kadar basit) Yeni bir .NET WinForms proje olun.
  • Bir ComboBox, bir düğmeye ve form üzerine (satırlı = Doğru ayarlanır) bir TextBox bırakın.
  • 3 özdeş öğeler ile ComboBox yüklemek için şu kodu kullanın ve ne zaman Selectedındexchanged olay yangınlar bazı durum iletilerini yazdırmak için ve seçili indeksi (bir düğme aracılığıyla) ne olduğunu görmek için:
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        TextBox1.Text = TextBox1.Text & vbNewLine & ComboBox SelectedIndexChanged event fired. & vbNewLine & _
            SelectedIndex is:  & ComboBox1.SelectedIndex
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ComboBox1.Items.Add(John Doe)
        ComboBox1.Items.Add(John Doe)
        ComboBox1.Items.Add(John Doe)

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TextBox1.Text = TextBox1.Text & vbNewLine & _
        Button clicked. & vbNewLine & _
        SelectedIndex is:  & ComboBox1.SelectedIndex
    End Sub

Projeyi çalıştırın ve ComboBox bir öğeyi (örneğin, ortadaki) seçin. Ardından, ComboBox'ın açılan oku tıklatın ancak HİÇBİRŞEY SEÇ YAPMAYIN. Düğme (varsayılan olarak Button1) tıklayın ve ne diyor bakın.

Aklımı kaybettim sürece, burada gördüğünüz gerekenler:

ComboBox Selectedındexchanged olay geçti.
Selectedındex: 1'dir
Düğme tıkladım.
Selectedındex geçerli: 0

Başka bir deyişle, SEÇİLMİŞ INDEX DEĞİŞTİ ama Selectedındexchanged olay ateş olmadan HAS!

ComboBox öğeler aynı olduğunda bu sadece olur. farklılar, bu olmaz. (ComboBox'ın Açılan tarzı olarak ayarlanırsa Ayrıca olmaz DropDownList.)

Bunun bir .NET framework kendisinde hata değil ben düzeltebilirim şey olabilir şüpheli, ama başkasının burada yapmak (ya da ne yanlış yapıyor olabilir!), Uymak lütfen gerekenlerle ilgili herhangi bir fikir olduğunu kapalı şans ! Ben onun etrafında bu davranışı veya çalışmalarını anlatmak üzere bir kayıp am (ben biliyorsun, aslında başka bir şey seçerek DEĞİŞTİRİN, sürece Selectedındex aynı kalmak bekliyoruz!)

Oluştur 09/12/2008 saat 23:04
kaynak kullanıcı
Diğer dillerde...                            


4 cevaplar

oy
17

.NET Framework aslında listede aşağı açılan kutunun damla seçilen endeksi takip etmez; Bu, Windows API tarafından dahili olarak işlenir. Bunun bir sonucu olarak, .NET, açılan kutunun pencere kolu gönderilen bir uyarı mesajı vasıtasıyla seçilen endeks değişimleri o da Selectedındexchanged olayı böylece ne zaman bildirmek için Windows API güvenmek durumundadır.

Ne yazık ki, (NET saatler özellikle bildirim mesajı çıkıyor CBN_SELCHANGEtam olarak) tüm olası senaryolar kapağı DEĞİLDİR hangi seçilen endeks değiştirebilir. Özellikle, CBN_SELCHANGEsadece kullanıcı tıkladığında veya ok tuşlarını, açılır listedeki bir öğeyi kullanarak seçerse, Windows API tarafından gönderilir. Ancak, DropDown tarzı açılan kutuda, açılan kutu açılması işlemi otomatik olarak bir eşleşme bulunursa, açılan kutunun düzenleme kısmında metne bakın bir maç için öğelerin listesi üzerinden arama yapabilir ve Windows neden olur (çoklu eşleştirme öğeleri olup olmadığını, ya da ilk eşleşen öğe) eşleştirme öğeyi seçin. Bu, seçilen endeksi değiştirebilirsiniz, ancak bir GÖNDERMEZ CBN_SELCHANGEbildirim mesajı, bu nedenle .NET değişti ve Selectedındexchanged olayı olmadığı gerçeği kaçırır.

Kullanıcı açılır listedeki bir şey almak için VAR olmadığından, Windows DropDown tarzı açılan kutu içinde tüm bu yok; ne isterlerse onu yazabilirsiniz. Yani açılan kutusunu açmak her zaman kullanıcı metni değiştirdi ve eğer listede ne ile tekrar senkronize etmeye çalışır olabileceğini varsayar.

Eğer ikinci kez açılan kutu açtığınızda durumda, bu yeniden senkronizasyon ve # 0 ve 0 olarak seçilen dizini olmaksızın değiştirme "John Doe" dir düzenlemek kısmında metin, ilk maçı seçilmesi olduğunu .NET farkında.

Yani temel .NET Framework bir hata olduğunu. Ne yazık ki, hiçbir mükemmel çözüm vardır - Eğer yeniden senkronizasyonu yapmamak Windows'u alamayan ve yeniden senkronize hangi yeni seçilen dizini alabilirsiniz oluşur hemen sonra patlar hiçbir olay yoktur. (Yeniden senkronize oluşur hemen önce DropDown olay aslında ateşler, bu nedenle yeni bir dizin görmez.) Yapabileceğiniz en iyi Hakkında, endeks bu noktada değişmiş olabileceğini varsaymak DropDownClosed olayını işlemek ve ona göre hareket olduğunu .

Cevap 10/12/2008 saat 04:29
kaynak kullanıcı

oy
2

Eric'in cevabı çok kapsamlı, ama sona etmediğini görünce şaşırdı "... ama yinelenen öğeleri ile açılan kutu doldurma neden gerçekten, kendinize sormalısınız." Net çerçeve hata şüphesiz bu hata içine tüketmemek, istediğiniz gibi kontrol kullandığınızda, kullanıcı bir listeden bir öğe seçmek için izin çünkü bulunmasına izin edilmiştir.

Nasıl kullanıcı aynı girişler arasında ayrım yapacak? Neden birbirleri üzerinde seçsin? farklı öğeleri için farklı bir anlamı var mıdır? Eğer öyleyse, o zaman çift giriş olmasıdır zaman kötü kullanılabilirlik tasarımı olan belirsiz. Değilse, o zaman yinelenen öğeleri olmamalıdır.

Eğer her iki bölümde görüntülemek istediğiniz böylece bir veya daha fazla öğe mantıksal olarak birden fazla gruba uyan ilgili öğeler, çeşitli gruplarından oluşan geniş bir liste var ben bu mantıklı olabilir nerede düşünebildiğim tek senaryodur.

Ben tasarım birden çok aynı girişleri olabileceğini ve bu ihmal bu sorundan çok daha önemli olan diğer kullanılabilirlik yankıları olacaktır gerçeğini dikkate almadılar tahmin ediyorum. Tabii ki, ben size yorumlarımı takmıyor olabilir ki bu durumda bu tamamen ne yaptığınızı yapmaya mantıklı olduğu düşünce değil bir şey yaptıkları anlıyoruz.

Cevap 30/03/2009 saat 07:54
kaynak kullanıcı

oy
1

Listede yinelenen öğeleri içeren geçerli ama arzu değil sadece durumlar vardır. Eğer Dosya Aç düğmesine bastığınızda Visual Studio gördüğünüz OpenFileDialog açılan kutu düşünün. Bu klasör adlarıyla vb 'Bilgisayarım', 'Masaüstü', 'Belgelerim' gibi öğelerle bir açılan kutu gösterir, ancak kısa adı listede olduğunu. tam yol gösterilmez. Ve böylece bir klasör onun soyundan biriyle aynı (kısa) adı vardır çok mümkündür.

Yani aşağıdaki klasör yapısını düşünün:

C:\
C:\A
C:\A\B
C:\A\B\A

Bir tamamen geçerli yapısı. Benim uygulamasında ben nesnelerin BindingList için DataSource özelliğini ayarlayın. Nesnenin ValueMember tam dosya adıdır ve DisplayMember kısa dosya adıdır. açılan kutu göstermesi gerekir:

C:\
    A
        B
            A

Gayet iyi UI tasarımı. girinti klasörlerin iç içe düşündürmektedir.

Ben Açılan kutunun SelectedValue batınca "C: A \ B \ A \" yanlış öğe seçilmiş olur. seçilmelidir öğe seçildiğinde listedeki son (4 öğe), ancak bunun yerine 2 öğe (dizin 1) 'dir. amaçlandığı gibi Ve Selectedındex = 3 ayar davranmaz. Yine, ikinci öğe son değil, seçilir.

Ne burada oluyor gibi görünmektedir SelectedValue veya Selectedındex ayarlarken, değer DisplayMember özelliğini kullanarak dönüştürülen ediliyor ve kontrol bir maç için başından sonuna kadar arama olmasıdır. Bu ValueMember özelliğini kullanarak arama yapılmalıdır. Örnek kod altındadır. Bunun bir hata ya da yanlış yapmış şeydir onaylayabilirse takdir.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace ComboBoxTest
{
   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         if (DesignMode)
            return;

         BindingList<CBItem> items = new BindingList<CBItem>();
         items.Add(new CBItem("A", @"C:\A"));
         items.Add(new CBItem("B", @"C:\A\B"));
         items.Add(new CBItem("A", @"C:\A\B\A"));

         comboBox.DisplayMember = "DisplayValue";
         comboBox.ValueMember = "RealValue";
         comboBox.DataSource = items;

         comboBox.SelectedValue = @"C:\A\B\A";
      }
   }

   class CBItem
   {
      public CBItem(string displayValue, string realValue)
      {
         _displayValue = displayValue;
         _realValue = realValue;
      }

      private readonly string _displayValue, _realValue;

      public string DisplayValue { get { return _displayValue; } }
      public string RealValue { get { return _realValue; } }
   }
}
Cevap 28/05/2009 saat 21:38
kaynak kullanıcı

oy
0

Benzer bir sorun, tam olarak uymuyor serbest metin, ancak ilk karakter girerseniz özdeş öğeler kalmadan gerçekleşir. Kullanıcı açılır listesini açın etmezse hiçbir yeniden senkronize olur ve seçilmiş endeksidir -1 beklendiği gibi. Şimdi kullanıcı pencereyi kapatır ve tekrar açın (öğelerden birini seçerek Değil kullanıcı yapmak istediği de budur). Sen, programcı olarak, kullanıcının girdiği ve metin otomatik olarak doldurulan madde kısmi eşleme olay ateş olmadan metin ile combobox geri yükleyin. kullanıcı iletişim kapatır metin haber verilmeksizin değişti. Metin herhangi bir öğeyi eşleşmiyor, bu sorun oluşmaz.

Cevap 28/06/2009 saat 11:15
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more