c# - WPF ListBox & Items with Changing Hashcode -
i have listbox
bound collection of items have id used generate result of gethashcode()
. when new item added, has id 0 until first saved our database. causing listbox
complain; believe reason because when item first used listbox
stored in internal dictionary
not expect hashcode change.
i can fix removing unsaved item collection (i must notify ui @ stage remove dictionary), save db, , add collection. messy , not have access collection save(businessobject obj)
method. have alternative solution problem?
edit in respose blam's answer:
i using mvvm have modified code use bindings. reproduce problem click add, select item, click save, repeat, try make selection. think demonstrates listbox
still holding onto old hashcodes in it's internal dictionary
, hence conflicting keys error.
<window x:class="listboxhashcode.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525"> <grid> <grid.rowdefinitions> <rowdefinition height="auto"/> <rowdefinition height="*"/> </grid.rowdefinitions> <stackpanel horizontalalignment="center" orientation="horizontal"> <button click="button_click_add" content="add"/> <button click="button_click_save" content="save selected"/> </stackpanel> <listbox grid.row="1" itemssource="{binding list}" displaymemberpath="id" selecteditem="{binding selected}"/> </grid> </window> public partial class mainwindow : window { public observablecollection<listitem> list { get; private set; } public listitem selected { get; set; } private int32 saveid; public mainwindow() { this.datacontext = this; this.list = new observablecollection<listitem>(); this.saveid = 100; initializecomponent(); } private void button_click_add(object sender, routedeventargs e) { this.list.add(new listitem(0)); } private void button_click_save(object sender, routedeventargs e) { if (selected != null && selected.id == 0) { selected.id = saveid; saveid++; } } }
edit 2 after testing, have discovered few things:
changing hash code of item in
listbox
seems work ok.changing hash code of the selected item in
listbox
breaks
it's functionality.
when selection made (single or multiple selection mode) ilist listbox.selecteditems
updated. items added selection added selecteditems
, items no longer included in selection removed.
if hash code of item changed while selected, there no way remove selecteditems
. manuallty calling selecteditems.remove(item)
, selecteditems.clear()
, setting selectedindex
-1 have no effect, , item remains in ilist
. causes exceptions thrown after next time selected believe once again added selecteditems
.
does have alternative solution problem?
hash code of object must not changed during object life-time. shouldn't use mutable data hash code calculation.
update.
i didn't expect, answer cause such discussion. here's detail explanation, may op.
let's @ mutable entity type defined in code, overrides gethashcode
and, of course, equals
. equality based on id
equality:
class mutable : iequatable<mutable> { public int id { get; set; } public override int gethashcode() { return id.gethashcode(); } public override bool equals(object obj) { if (obj == null) { return false; } var mutable = obj mutable; if (mutable == null) { return false; } return this.equals(mutable); } public bool equals(mutable other) { return id.equals(other.id); } }
somewhere in code you've created several instances of type:
// here's mutable entities hash-code, calculated using mutable data: var key1 = new mutable { id = 1 }; var key2 = new mutable { id = 2 }; var key3 = new mutable { id = 3 };
and external code, uses dictionary<mutable, string>
internal purposes:
// let's use them key dictionary: var dictionary = new dictionary<mutable, string> { { key1, "john" }, { key2, "mary" }, { key3, "peter" } }; // ok, of keys located properly: console.writeline(dictionary[key1]); console.writeline(dictionary[key2]); console.writeline(dictionary[key3]);
again, code. suppose, you've changed id
of key1
. hash-code changed too:
// let's change hashcode of key1: key1.id = 4;
and again, external code. here tries locate data key1
:
console.writeline(dictionary[key1]); // ooops! key1 not found in dictionary
of course, can design mutable types, overrides gethashcode
, equals
, , calculate hash-code on mutable data. shouldn't that, (except cases, when know, doing).
you can't guarantee, external code won't use dictionary<tkey, tvalue>
or hashset<t>
internally.
Comments
Post a Comment