2011-10-10 34 views
13

Gần đây tôi đã gặp sự cố trong đó tôi có một ObservableCollection được liên kết với một ListView. Con người là một cấu trúc mà tôi đã viết. Vì vậy, miễn là tôi đặt giá trị (s) của các đối tượng People trước khi ràng buộc, mọi thứ dường như hoạt động OK. Tuy nhiên, khi tôi cố gắng thiết lập các giá trị từ GUI khi chạy, các đối tượng bên dưới dường như không phản ánh thay đổi.Tại sao việc ràng buộc vào một cấu trúc không hoạt động?

Cuối cùng tôi đã vượt qua vấn đề này bằng cách đơn giản thay đổi Mọi người từ một cấu trúc thành một lớp học. Không có thay đổi nào khác là cần thiết.

Ai đó có thể vui lòng giải thích cho tôi lý do tại sao điều này không?

+5

bạn có biết sự khác biệt giữa cấu trúc và lớp học? –

Trả lời

21

Ràng buộc của bạn nhận được bản sao của cấu trúc vì cấu trúc được truyền theo giá trị cho phương thức. Nếu ràng buộc cập nhật một cái gì đó; một bản sao trong bộ nhớ ở đâu đó đang được sửa đổi và do đó đối tượng gốc của bạn không được cập nhật.

2

Vì cấu trúc được truyền theo giá trị cho điều khiển, do đó khi bạn thực hiện thay đổi trong giao diện người dùng, WPF sẽ ghi lại các thay đổi về một phiên bản khác là People.

Thay đổi nó thành một lớp và nó sẽ hoạt động.

Trừ khi bạn hoàn toàn hiểu mục đích của struct Tôi khuyên bạn không nên sử dụng nó.

2

Các ListView là một ItemsControl và các công trình hoặc trong chế độ trực tiếp, nơi bạn cư đó là mục bằng cách tuyên bố đối tượng ListViewItem severl trong XAML hoặc trong chế độ ItemsSource nơi bạn thiết lập một ràng buộc về tài sản

See this Dr. WPF article for a good explanation ItemsSource. Dù bằng cách nào, ListView.Items là một ItemCollection là một CollectionView, tức là Items không phải là bộ sưu tập thực tế mà bạn cung cấp cho thuộc tính ItemsSource mà là một bản sao chuẩn hóa của bộ sưu tập mà bạn cung cấp, cho phép khuôn khổ để truy cập ví dụ IEnumerable cơ bản theo chỉ mục mặc dù IEnumerable không cung cấp một trình chỉ mục.

Vì ListView sử dụng bản sao, khi sử dụng tập hợp các phiên bản Lớp, nó có thể tạo bản sao tham chiếu, cả hai tham chiếu đều trỏ đến cùng một đối tượng trong bộ nhớ để ảnh hưởng của việc thay đổi giá trị trong một trong các tham chiếu thông qua tham chiếu khác, nhưng khi sử dụng tập hợp các cấu trúc là các kiểu giá trị, nó phải tạo bản sao của các giá trị, thay vì có hai tham chiếu trỏ đến cùng một đối tượng, thì bạn có hai đối tượng kiểu giá trị riêng biệt.

1

Đối với tất cả những người quan tâm đến chủ đề này: Tôi đã chạy nó, với Combobox và Objectdataprovider. "ItemsSource" là cấu trúc, nhưng "SelectedItem" được viết ở một nơi khác. Ở đây là:

<!--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}}"/> 

Và đây là cách cấu trúc trông giống như:

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; 
    } 
} 
Các vấn đề liên quan