2013-03-12 17 views
5

Bir iki gün için garip bir WPF hatası bulmaya çalışıyorum. Bir ındegopoperty ve IEquatable sınıfı bir uygulama olan ve Id (bir dize) adlı tek bir alana sahip olan bir GözlemciKoleksiyon İlkesi'ne bağlı bir ListBox ile bir denetimim var. PolicyId'ler, programın diğer kısımlarındaki iş akışını değiştiren çeşitli poliklinik öğelerinin işaretçileridir.ListBox seçili veri değiştirildiği zaman seçili olanı değiştirme yeteneğini kaybeder

ListBox, koleksiyona bağlıdır ve yalnızca Id'leri ListBox'a ekleyip kaldıran bir ekleme ve kaldırma düğmesi vardır. Ayrıca, ListBox'daki selectedItem öğesinin PolicyId öğesinin başka bir kimlikle değiştirilebilmesi için açılan bir ComboBox da vardır (seçim için seçilebilecek Kimlikler başka yerde değiştirilmiştir). ListBox.SelectedItem.Id özelliği değerini ayarlamak, ComboBox.SelectionChanged olay tetiklendiğinde arka uçta yapılır ve ListBox.SelectionChanged olay tetiklendiğinde ComboBox'taki değerler değiştirilir, bu, öğelerin hiçbirinin ListBox aynıdır. Şimdi, bu uygulama çoğu için çalışıyor. Tüm politikalar ListBox'ta listelenir ve yenilerini ekleyebilir (bu, listenin en altında önceden seçilmemiş olan ilk seçeneği belirleyebilir) ve istediğiniz herhangi bir politikayı seçip kaldırabilirsiniz.

Bir ilkeyi, birleşik giriş kutusunu kullanarak başka biriyle değiştirmediğiniz sürece. Bunu yaptıktan sonra dizin değiştirdiğinize yapışır ve başka bir politika seçmek için yapabileceğiniz bir şey yoktur (ListBox.SelectedIndex'in ayarının bir etkisi yoktur). Yeterince uzun tıklayıp sonunda aşağıdaki istisna atılır: "System.ArgumentException: Aynı tuşa sahip bir öğe zaten eklendi." WPF tarafından, öğe zaten zaten veya böyle bir şey olsa bile, seçili öğeyi listBox'un "selectedItems" koleksiyonuna eklemeye çalışan WPF'den kaynaklandığından şüpheleniyorum.

Böceklerin PolicyId'i geçersiz kılan Equals ile ilgili bir şey olduğunu biliyorum (evet, Eşitlerin iki nesnenin birbirine eşit olduğunu söylerse GetHashCode'un aynı değer için iki tane de döndürmesi gerektiğini unutmayın, bu nedenle GetHashCode Aynı zamanda geçersiz kılınmış) çünkü programın başka bir yerinde problemsiz bir kurulum kullanılır. Bu, özellikle de koleksiyonda hiç kopya olmadığı için, bunun nasıl berbat olduğunu bilmiyorum.

<ListBox Name="policyIdList" MinHeight="50" ItemsSource="{Binding Path=DataItem}" IsSynchronizedWithCurrentItem="True" SelectionChanged="policyIdList_SelectionChanged"> 
    <ListBox.Resources> 
     <Style TargetType="ScrollViewer"> 
      <Setter Property="HorizontalScrollBarVisibility" Value="Hidden" /> 
     </Style> 
    </ListBox.Resources> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock DataContext="{Binding Path=Id}" Text="{Binding Converter={StaticResource PolicyIdToName}}"> 
       <TextBlock.ToolTip> 
        <ContentControl Content="{Binding}" ContentTemplate="{StaticResource PolicyByOidListItem}" /> 
       </TextBlock.ToolTip> 
      </TextBlock> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Ve iyi önlemler için, combobox:

Bu ListBox

<ComboBox Name="policyIdCombo" Grid.Row="1" Grid.Column="0" 
ItemTemplate="{StaticResource PolicyByOidListItem}" SelectionChanged="policyIdCombo_SelectionChanged" /> 
+0

PolicyId sınıfınız 'Equals''ı geçersiz kılarsa, aynı zamanda GetHashCode'u geçersiz kılar mı?[Eşittir] 'in Açıklamalar bölümünde (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx): "Eşittir (Object)' i geçersiz kılan türler, GetHashCode'u da geçersiz kılar. Aksi takdirde, karma tablolar doğru şekilde çalış. Belki de bu bir şekilde probleminizin kaynağıdır, en azından 'GetHashCode''u geçersiz kılmak yanlış değildir. – Clemens

+0

Öyle, öyle değil. Ben sadece GetHashCode'u da geçersiz kılmayı hatırladığımı söylemeyi unuttum (bunu şimdi ekledim). Her neyse, her iki yöntemin de doğru olan tek bir alan olması gerçekten çok önemsizdir (aynı sınıfın ikisi de aynıysa, alanı karşılaştırın, sonra GetHashCode'da field.GetHashCode() değerini döndürün), GetHashCode'u bildiğiniz sürece Eşittir işaretlerini true olarak doğrulayan nesneler için aynı kargayı döndürmelidir. –

cevap

9

Sorunun bunu kimliğin değiştirdiğinizde öğenin karma kodunun changning olduğunu düşünüyorum, ve ListBox bunu beklemiyor. Daha fazla bilgi için See here.

Sadece bir uygulamayı .NET 3.5'ten 4.0'a yükselttim ve bu sorunla karşılaştı. Benim gibi sabit bir hashcode kullanmak mümkün değilse o zaman bir geçici çözüm:

  1. değişim
  2. Değişim ait kimliği UI bildir nesne listesinde
  3. değiştirilebilir için kaldırılsın nesne (hashcode için bir değişiklikle sonuçlanan)
  4. Nesnenizi tekrar listeye ekleyin ve değişikliğin kullanıcı arayüzüne bildirin.
+0

Teşekkürler, tesadüfen, sonuçta nasıl (bilinçsizce) çözdüğümüz budur - ürün değiştirme işlemi çalışmadığı için yalnızca politika eklemeye ve kaldırmaya izin verdik. Açılan kutu, eklenecek ilkeyi seçmek için kullanıldı. –