Frage

Ich bin mit einer List-Box eine Liste der Elemente in einer WPF-Anwendung zu halten. Die List-Box-Datenquelle ist ein HashSet in einem ObservableCollection gewickelt. dh ich habe den folgenden Code:

this.shackSet = new ObservableCollection<Shack>(new HashSet<Shack>());
this.shackListing.ItemsSource = this.shackSet;

... wo shackListing ist ein Steuerelement List-Box und shackSet in eine ICollection. Jedes Mal, wenn ich etwas zu shackSet nach der Zugabe des ersten Elements hinzufügen, sehe ich mehrere Artikel in der List-Box. dh Es ist wie neu hinzugefügte Elemente werden immer in die Liste aufgenommen, unabhängig davon, ob sie zu dem Satz hinzugefügt sind. Wenn ich mir die Unterschriften von ICollection # Anzahl:

void Add(T obj);

... und HashSet # Anzahl:

bool Add(T obj); 

... Dies führt mich zu glauben, dass es ein Fehler ist, die eingewickelt HashSets betroffen, in denen neu hinzugefügte Elemente in der List-Box hinzugefügt bekommen, unabhängig, weil die ObservableCollection keine Möglichkeit hat, zu sagen, ob das Objekt tatsächlich in die darunter liegenden Sammlung hinzugefügt wurde, weil der Rückgabetyp von ICollection ist # Add Leere. Kann jemand anderes bestätigt das?

War es hilfreich?

Lösung

Wenn Sie eine neue ObservableCollection mit einer anderen Sammlung erstellen Sie nicht, dass die Sammlung wickeln, erstellen Sie einen neuen, in der alle Elemente der übergebenen Sammlung an die ObservableCollection kopiert werden. Wenn Sie eine ObservableCollection für den alleinigen Zweck der Datenbindung verwenden möchten, suchen Sie nicht weiter, können Sie zu jedem IEnumerable in WPF binden. Dies hat den Nachteil, dass Unfortuantely WPF nicht immer korrekt pickup Änderungen an der gebundene Sammlung. Wenn dies ein Problem ist, würden Sie wahrscheinlich haben, um Ihre eigene obeservable Hashset zu erstellen:

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); 
    } 
}

EDIT: Wie bereits erwähnt wurde, können Sie nicht von HashSet erben INotifyCollectionChanged zu implementieren. Allerdings, wenn Sie auf dem Code (mit Reflektor) suchen die HashSet Klasse ist es ziemlich einfach, es zu schwer zu imitieren sein soll, dass Funktionalität selbst.

Andere Tipps

Wie pro bitbonk Antwort, aber ich wollte das Add (T Artikel) -Methode außer Kraft zu setzen, aber man kann nicht, so dass ich eine Append (T Artikel) erstellt Methode statt:

public class ObservableSetCollection<T> : ObservableCollection<T> {
    public void Append(T item) {
        if (Contains(item)) return;
        base.Add(item);
    }
}

Und dann in meinem Code hinter:

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());
    }
}

In der oben Ich habe zwei Listboxen, listboxAvailableColumns, die eine Liste von Zeichenketten hat, dass der Benutzer durch Doppelklick auswählen können, die die Auswahl mit dem zweiten Listenfeld fügt hinzu, listboxConsolidationColumns. Keine Duplikate sind erlaubt, und das funktioniert perfekt mit dem ObservableSetCollection genau wie oben.

Das XAML ist einfach:

<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>

Wie bitbonk sagte ObservableCollection nicht die Hashset einzuwickeln, aber kopiert seine Elemente statt.

Wenn Sie eine beobachtbare Hashset wollen überprüfen Wie kann ich machen einen beobachtbaren Hashset in C #?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top