c# – wpf DataGrid – 已添加具有相同键的项

前端之家收集整理的这篇文章主要介绍了c# – wpf DataGrid – 已添加具有相同键的项前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我看到很多与此问题相关的帖子,但我找不到解决方

我有下一个WPF DataGrid:

  1. <DataGrid Grid.Column="1"
  2. Grid.Row="4"
  3. AutoGenerateColumns="False"
  4. ItemsSource="{Binding MapsGrid}"
  5. SelectedItem="{Binding DataContext.CategoriesSelectedRow,RelativeSource={RelativeSource AncestorType={x:Type UserControl}},Mode=OneWayToSource}"
  6. SelectionMode="Single"
  7. CanUserReorderColumns="False"
  8. CanUserResizeColumns="False"
  9. CanUserDeleteRows="False"
  10. CanUserResizeRows="False"
  11. CanUserAddRows="False">
  12. <DataGrid.Columns>
  13. <DataGridTemplateColumn Header="Main Category"
  14. Width="*">
  15. <DataGridTemplateColumn.HeaderStyle>
  16. <Style TargetType="DataGridColumnHeader">
  17. <Setter Property="HorizontalContentAlignment"
  18. Value="Center" />
  19. <Setter Property="FontSize"
  20. Value="16" />
  21. </Style>
  22. </DataGridTemplateColumn.HeaderStyle>
  23. <DataGridTemplateColumn.CellTemplate>
  24. <DataTemplate>
  25. <ComboBox ItemsSource="{Binding MainCategoriesColl}"
  26. DisplayMemberPath="Category"
  27. SelectedItem="{Binding MainCategorySelectedItem,UpdateSourceTrigger=LostFocus,Mode=OneWayToSource}" />
  28. </DataTemplate>
  29. </DataGridTemplateColumn.CellTemplate>
  30. </DataGridTemplateColumn>
  31.  
  32. <DataGridTemplateColumn Header="Sub Category"
  33. Width="*">
  34. <DataGridTemplateColumn.HeaderStyle>
  35. <Style TargetType="DataGridColumnHeader">
  36. <Setter Property="HorizontalContentAlignment"
  37. Value="Center" />
  38. <Setter Property="FontSize"
  39. Value="16" />
  40. </Style>
  41. </DataGridTemplateColumn.HeaderStyle>
  42. <DataGridTemplateColumn.CellTemplate>
  43. <DataTemplate>
  44. <ComboBox ItemsSource="{Binding SubCategoriesColl}"
  45. DisplayMemberPath="Category"
  46. SelectedItem="{Binding SubCategorySelectedItem,Mode=TwoWay}" />
  47. </DataTemplate>
  48. </DataGridTemplateColumn.CellTemplate>
  49. </DataGridTemplateColumn>
  50. </DataGrid.Columns>
  51. </DataGrid>

这个DataGrid包含2个ComboBoxes. ItemSource对象是下一个:

  1. public class MapsDescModel : NotificationObject,IEqualityComparer<MapsDescModel>,IEquatable<MapsDescModel>
  2. {
  3. public MapsDescModel(ObservableCollection<MainCategories> mainCategoty)
  4. {
  5. MainCategoriesColl = mainCategoty;
  6.  
  7. }
  8.  
  9. public static event Action OnSelectionHandler;
  10.  
  11. private static void OnSelection()
  12. {
  13. if (OnSelectionHandler != null)
  14. {
  15. OnSelectionHandler();
  16. }
  17. }
  18.  
  19. private MainCategories _mainCategorySelectedItem;
  20. public MainCategories MainCategorySelectedItem
  21. {
  22. get { return _mainCategorySelectedItem; }
  23. set
  24. {
  25. if (Equals(value,_mainCategorySelectedItem)) return;
  26. _mainCategorySelectedItem = value;
  27. RaisePropertyChanged("MainCategorySelectedItem");
  28. RaisePropertyChanged("SubCategoriesColl");
  29. }
  30. }
  31.  
  32. private SubCategories _subCategorySelectedItem;
  33. public SubCategories SubCategorySelectedItem
  34. {
  35. get { return _subCategorySelectedItem; }
  36. set
  37. {
  38. if (Equals(value,_subCategorySelectedItem)) return;
  39. _subCategorySelectedItem = value;
  40. RaisePropertyChanged("SubCategorySelectedItem");
  41. OnSelection();
  42.  
  43. }
  44. }
  45.  
  46.  
  47. private ObservableCollection<MainCategories> _mainCategoriesColl;
  48. public ObservableCollection<MainCategories> MainCategoriesColl
  49. {
  50. get { return _mainCategoriesColl; }
  51. set
  52. {
  53. if (Equals(value,_mainCategoriesColl)) return;
  54. _mainCategoriesColl = value;
  55. RaisePropertyChanged("MainCategoriesColl");
  56. }
  57. }
  58.  
  59.  
  60. //Allow user see N/A category just if is the only subCategory that exists
  61. public ObservableCollection<SubCategories> SubCategoriesColl
  62. {
  63. get
  64. {
  65. if (MainCategorySelectedItem != null && MainCategorySelectedItem.SubCategory.Any())
  66. if (MainCategorySelectedItem.SubCategory.Count() > 1)
  67. {
  68. return Infrastructure.Helpers.ExtensionMethods.ToObservableCollection(
  69. MainCategorySelectedItem.SubCategory.AsEnumerable().Where(p => p.Category != Infrastructure.Constants.Constants.NoSubCategory));
  70. }
  71. else return Infrastructure.Helpers.ExtensionMethods.ToObservableCollection(
  72. MainCategorySelectedItem.SubCategory.AsEnumerable());
  73. else return new ObservableCollection<SubCategories>();
  74. }
  75. }
  76.  
  77.  
  78. public bool Equals(MapsDescModel x,MapsDescModel y)
  79. {
  80. try
  81. {
  82. if (x.MainCategorySelectedItem == null && y.MainCategorySelectedItem == null)
  83. return true;
  84. else if (x.MainCategorySelectedItem == null && y.MainCategorySelectedItem != null ||
  85. x.MainCategorySelectedItem != null && y.MainCategorySelectedItem == null)
  86. return false;
  87. return
  88. x.MainCategorySelectedItem.MainCatID == y.MainCategorySelectedItem.MainCatID &&
  89. x.SubCategorySelectedItem.SubCatID == y.SubCategorySelectedItem.SubCatID;
  90. }
  91. catch (Exception ex)
  92. {
  93. ServiceLocator.Current.GetInstance<Infrastructure.SharedServices.IEnterpriseLibraryLogger>().Log(ex.Message,Category.Exception,Priority.High);
  94. return false;
  95. }
  96. }
  97.  
  98. public int GetHashCode(MapsDescModel obj)
  99. {
  100. if (Object.ReferenceEquals(obj,null)) return 0;
  101.  
  102. if (obj.MainCategorySelectedItem == null || obj.SubCategorySelectedItem == null)
  103. return 0;
  104. else return obj.SubCategorySelectedItem.Category.GetHashCode() + obj.MainCategorySelectedItem.GetHashCode();
  105. }
  106.  
  107. public bool Equals(MapsDescModel other)
  108. {
  109. return
  110. this.Equals(this,other); // use definition from IEqualityComparer<T>
  111. }
  112.  
  113. public override bool Equals(object obj)
  114. {
  115. MapsDescModel other = obj as MapsDescModel;
  116. if (other == null)
  117. return base.Equals(obj);
  118. else
  119. return this.Equals(other);
  120. }
  121.  
  122. public override int GetHashCode()
  123. {
  124. MapsDescModel other = this as MapsDescModel;
  125. if (other == null)
  126. return base.GetHashCode();
  127. else
  128. return this.GetHashCode(other);
  129. }
  130. }

一切都很好,除了一个恼人的问题.
当我添加2行时,如果我在附加图片中的标记区域上单击几次,则会出现以下错误

  1. System.ArgumentException was unhandled
  2. HResult=-2147024809
  3. Message=An item with the same key has already been added.
  4. Source=mscorlib
  5. StackTrace:
  6. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
  7. at System.Collections.Generic.Dictionary`2.Insert(TKey key,TValue value,Boolean add)
  8. at System.Collections.Generic.Dictionary`2..ctor(IDictionary`2 dictionary,IEqualityComparer`1 comparer)
  9. at System.Windows.Controls.Primitives.Selector.InternalSelectedItemsStorage..ctor(InternalSelectedItemsStorage collection,IEqualityComparer`1 equalityComparer)
  10. at System.Windows.Controls.Primitives.Selector.SelectionChanger.ApplyCanSelectMultiple()
  11. at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
  12. at System.Windows.Controls.SelectedItemCollection.EndUpdateSelectedItems()
  13. at System.Windows.Controls.Primitives.MultiSelector.EndUpdateSelectedItems()
  14. at System.Windows.Controls.DataGrid.MakeFullRowSelection(ItemInfo info,Boolean allowsExtendSelect,Boolean allowsMinimalSelect)
  15. at System.Windows.Controls.DataGrid.HandleSelectionForRowHeaderAndDetailsInput(DataGridRow row,Boolean startDragging)
  16. at System.Windows.Controls.Primitives.DataGridRowHeader.OnClick()
  17. at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonDown(MouseButtonEventArgs e)
  18. at System.Windows.UIElement.OnMouseLeftButtonDownThunk(Object sender,MouseButtonEventArgs e)
  19. at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler,Object genericTarget)
  20. at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler,Object target)
  21. at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target,RoutedEventArgs routedEventArgs)
  22. at System.Windows.EventRoute.InvokeHandlersImpl(Object source,RoutedEventArgs args,Boolean reRaised)
  23. at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender,RoutedEvent newEvent)
  24. at System.Windows.UIElement.OnMouseDownThunk(Object sender,Boolean reRaised)
  25. at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender,RoutedEventArgs args)
  26. at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
  27. at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args,Boolean trusted)
  28. at System.Windows.Input.InputManager.ProcessStagingArea()
  29. at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
  30. at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
  31. at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd,InputMode mode,Int32 timestamp,RawMouseActions actions,Int32 x,Int32 y,Int32 wheel)
  32. at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd,WindowMessage msg,IntPtr wParam,IntPtr lParam,Boolean& handled)
  33. at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd,Int32 msg,Boolean& handled)
  34. at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd,Boolean& handled)
  35. at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
  36. at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback,Object args,Int32 numArgs)
  37. at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source,Delegate method,Int32 numArgs,Delegate catchHandler)
  38. at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority,TimeSpan timeout,Int32 numArgs)
  39. at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd,IntPtr lParam)
  40. at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
  41. at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
  42. at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
  43. at System.Windows.Threading.Dispatcher.Run()
  44. at System.Windows.Application.RunDispatcher(Object ignore)
  45. at System.Windows.Application.RunInternal(Window window)
  46. at System.Windows.Application.Run(Window window)
  47. at System.Windows.Application.Run()
  48. at Malaria.App.Main() in c:\My Projects\Hebrew University\Malaria Management Console\Malaria\obj\Debug\App.g.cs:line 0
  49. at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly,String[] args)
  50. at System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String[] args)
  51. at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
  52. at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
  53. at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
  54. at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state)
  55. at System.Threading.ThreadHelper.ThreadStart()
  56. InnerException:

我认为它可能与我的GetHashCode方法有关,但我不确定.
我找到了这个链接
http://leavinsprogramming.blogspot.co.il/2012/08/wpf-datagrid-and-random.html
它描述了我的问题,但那里没有解决方案.
有谁知道为什么会发生这种异常?

解决方法

引用 MSDN’s entry on Object.GetHashCode()

In general,for mutable reference types,you should override GetHashCode only if:

  • You can compute the hash code from fields that are not mutable; or

  • You can ensure that the hash code of a mutable object does not change while the object is contained in a collection that relies on its hash code.

您当前的GetHashCode()实现调用GetHashCode(MapsDescModel obj),该方法依赖于可在集合中更改的可变字段.

更改GetHashCode()实现以返回不依赖于可更改字段的值.

猜你在找的C#相关文章