WPFでのObservableCollectionでHashSetsを使用します
-
22-09-2019 - |
質問
私は、WPFアプリケーション内の項目のリストを維持するために、リストボックスを使用しています。リストボックスのデータソースは、のObservableCollectionに包まれたHashSetのです。つまり、私は次のコードを持っています:
this.shackSet = new ObservableCollection<Shack>(new HashSet<Shack>());
this.shackListing.ItemsSource = this.shackSet;
... shackListingがいるICollectionにリストボックスコントロールであり、そしてshackSet。私は最初の項目を追加した後、shackSetに何かを追加するたびにしかし、私は、リストボックスで複数の項目を参照してください。新しく追加された項目に関係なく、彼らがセットに追加しているかどうかのリストに追加取得しているように、すなわちそれはです。私がいるICollectionを#の追加の署名を見てみると:
void Add(T obj);
...とHashSetの番号を追加します。
bool Add(T obj);
...私はのObservableCollectionは、オブジェクトが実際に下層コレクションに追加されたかどうかを伝える方法がないため、新たに追加された項目に関係なく、リストボックスに追加されます包まれたHashSetsに影響バグがあります信じて、このリード戻り値の型ので、 ICollectionを番号の追加の空隙です。缶誰でも他に確認この?
解決
あなたはそのコレクションをラップしていない別のコレクションを持つ新しいのObservableCollectionを作成するときに、あなたが渡されたコレクションのすべての項目はのObservableCollectionにコピーされ、新しいものを作成します。あなたは、データバインディングの唯一の目的のためのObservableCollectionを使用するもう探す必要はありませんしたい場合は、WPFでの任意のIEnumerableをと結合することができます。これはunfortuantelyバインドされたコレクションにWPFはなりません常に正しくピックアップ変化という欠点があります。これは問題がある場合は、おそらくあなた自身のobeservable HashSetのを作成する必要があると思います:
public class ObservableHashSet<T> : ObservableCollection<T>
{
protected override void InsertItem(int index, T item)
{
if (Contains(item))
{
throw new ItemExistsException(item);
}
base.InsertItem(index, item);
}
protected override void SetItem(int index, T item)
{
int i = IndexOf(item);
if (i >= 0 && i != index)
{
throw new ItemExistsException(item);
}
base.SetItem(index, item);
}
}
編集: ASすでに指摘されている、あなたはINotifyCollectionChangedを実装するためのHashSetから継承することはできません。あなたがHashSetのクラスの(リフレクターを使用して)コードを見ればしかし、それは模倣その機能にあまりにもハード自分自身であるべき非常に単純です。
他のヒント
、bitbonkの答えを1として、私は、add(Tアイテム)メソッドをオーバーライドしたかったが、あなたがすることはできません。
public class ObservableSetCollection<T> : ObservableCollection<T> {
public void Append(T item) {
if (Contains(item)) return;
base.Add(item);
}
}
そして、私のコードで背後ます:
public partial class MainWindow : Window {
private ObservableSetCollection<string> consolidationHeaders;
public MainWindow() {
InitializeComponent();
initialize();
}
private void initialize() {
consolidationHeaders = new ObservableSetCollection<string>();
listboxConsolidationColumns.ItemsSource = consolidationHeaders;
}
.
.
.
private void listboxAvailableColumns_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
consolidationHeaders.Append(listboxAvailableColumns.SelectedValue.ToString());
}
private void listboxConsolidationColumns_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
consolidationHeaders.Remove(listboxConsolidationColumns.SelectedValue.ToString());
}
}
私は、ユーザが第2のリストボックスに選択を追加し、ダブルクリック、listboxConsolidationColumnsによって選択できるという文字列のリストを持っている2つのリストボックス、listboxAvailableColumnsを、持っている上記で。いいえ、重複が許可されていない、これは正確に上記のようObservableSetCollectionで完璧に動作します。
XAMLは単純です:
<Grid Margin="5,5,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Available Columns"/>
<Label Grid.Row="0" Grid.Column="1" Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Consolidation Columns"/>
<ListBox Grid.Row="1" Grid.Column="0" Name="listboxAvailableColumns" MouseDoubleClick="listboxAvailableColumns_MouseDoubleClick" />
<ListBox Grid.Row="1" Grid.Column="1" Name="listboxConsolidationColumns" MouseDoubleClick="listboxConsolidationColumns_MouseDoubleClick" />
</Grid>
のObservableCollectionはHashSetの代わりにコピーし、その要素をラップしない、と述べています。
あなたが観察HashSetのをしたい場合は、で観察HashSetのを作ります