2011-10-10 16 views
13

Niedawno napotkano na problem, który powoduje, że obserwowalna kolekcja jest powiązana z ListView. Ludzie to struktura, którą napisałem. Dopóki ustawiam wartości obiektów People przed powiązaniem, wszystko wydaje się działać poprawnie. Jednak gdy próbuję ustawić wartości z GUI w czasie wykonywania, podstawowe obiekty nie wydają się odzwierciedlać zmiany.Dlaczego powiązanie z konstrukcją nie działa?

W końcu udało mi się przezwyciężyć ten problem, po prostu zmieniając ludzi ze struktury na klasy. Żadne inne zmiany nie były konieczne.

Czy ktoś może mi wyjaśnić, dlaczego tak jest?

+5

znasz różnicę między struct i klasy? –

Odpowiedz

21

Wiązanie otrzymuje kopię struktury, ponieważ struktury są przekazywane wartościom metodom. Jeśli powiązanie coś zaktualizuje; kopia w pamięci gdzieś jest modyfikowana, a więc oryginalny obiekt nie jest aktualizowany.

2

Ponieważ struktura jest przekazywana przez wartość do formantu, dlatego po wprowadzeniu zmian w interfejsie WPF zapisuje zmiany z powrotem do innego wystąpienia People.

Zmień na klasę, a to zadziała.

Jeśli nie rozumiesz w pełni celu urządzenia struct, sugeruję, aby go nie używać.

2

ListView jest ItemsControl i działa zarówno w trybie bezpośrednim, gdzie zapełnić to przedmioty deklarując severl obiektów ListViewItem w XAML lub w trybie ItemsSource gdzie ustawić Oprawa na posesji ItemsSource

See this Dr. WPF article for a good explanation.

Tak czy inaczej, ListView.Items jest Kolekcja przedmiotów, która jest CollectionView, tj. Elementy nie są rzeczywistą kolekcją dostarczaną do właściwości ItemsSource, ale znormalizowaną kopią dostarczonej kolekcji, która umożliwia ramie na przykład dostęp do under IEnumerable by index, mimo że IEnumerable nie dostarcza samego indeksu.

Ponieważ ListView używa kopii, gdy używa kolekcji instancji klasy, może wykonywać kopie odniesień, oba odniesienia wskazują na ten sam obiekt w pamięci, dzięki czemu widoczne są efekty zmiany wartości w jednym z odniesień poprzez inne odwołanie, ale kiedy używa zbioru typów, które są typami wartości, musi tworzyć kopie wartości, zamiast dwóch odniesień, które wskazują ten sam obiekt, wtedy masz dwa obiekty o różnych wartościach.

1

Dla wszystkich zainteresowanych w tym temacie: Mam go uruchomiony, z Combobox i Objectdataprovider. "ItemsSource" jest strukturą, ale "SelectedItem" jest zapisane gdzie indziej. Oto ona:

<!--resources--> 
    <ObjectDataProvider x:Key="StructValues" 
         MethodName="GetValues" 
         ObjectType="{x:Type local:MyStruct}"> 
     <ObjectDataProvider.MethodParameters> 
      <x:Type TypeName="local:MyStruct" /> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 

    <ComboBox Margin="0,5" 
         VerticalAlignment="Center" 
         ItemsSource="{Binding Source={StaticResource StructValues}}"/> 

A to, w jaki sposób struktura wygląda następująco:

public struct MyStruct 
{ 
    public const string A = "A"; 
    public const string B = "B"; 
    public const string C = "C"; 

    public static IEnumerable GetValues(Type type) 
    { 
     List<String> retVals = new List<string>(); 
     FieldInfo[] fi = type.GetFields(); 
     foreach (FieldInfo info in fi) 
     { 
      retVals.Add(info.Name); 
     } 
     return retVals; 
    } 
} 
Powiązane problemy