2011-11-22 27 views
5

Tôi có dữ liệu mẫu sau đây, mà làm việc ra độc đáo ...Tái sử dụng dữ liệu thiết kế trong Expression Blend?

<SampleData:DashboardViewModel xmlns:SampleData="clr-namespace:MyApp.ViewModels"> 
    <SampleData:DashboardViewModel.Employees> 
     <SampleData:EmployeeViewModel FirstName="Aaron" "Adams" /> 
     <SampleData:EmployeeViewModel FirstName="Billy" "Bob" /> 
     <SampleData:EmployeeViewModel FirstName="Charlie" "Chaplin" /> 
    </SampleData:DashboardViewModel.Employees> 
</SampleData:DashboardViewModel> 

Tuy nhiên, tôi thấy rằng nó sẽ hữu ích để có thể tái sử dụng mà danh sách các nhân viên mẫu thay vì gõ lại nó mỗi lần. Tôi không thể tìm ra cách sử dụng lại danh sách đó. Về cơ bản, tôi muốn có một tập tin SampleData (SampleEmployees.xaml) chứa rằng danh sách của người lao động, sau đó có thể làm việc này trong các mẫu khác của tôi ...

<SampleData:DashboardViewModel xmlns:SampleData="clr-namespace:MyApp.ViewModels"> 
    <SampleData:DashboardViewModel.Employees ... /> <!-- What goes in there? --> 
</SampleData:DashboardViewModel> 

<SampleData:OtherViewModel xmlns:SampleData="clr-namespace:MyApp.ViewModels"> 
    <SampleData:OtherViewModel.Employees ... /> <!-- What goes in there? --> 
</SampleData:OtherViewModel> 

Ngoài ra, làm thế nào để tạo danh sách riêng trong một tệp XAML khác ??

ViewModel:

public class DashboardViewModel : NotificationObject 
{ 
    public class DashboardViewModel(IDataService dataService) 
    { 
     InternalEmployees = new ObservableCollection<EmployeeViewModel>(dataService.GetEmployees()); 
     Employees = new ReadOnlyObservableCollection<EmployeeViewModel>(InternalEmployees); 
    } 

    private ObservableCollection<EmployeeViewModel> InternalEmployees { get; set; } 
    public ReadOnlyObservableCollection<EmployeeViewModel> Employees { get; private set; } 
} 
+0

Tôi không nghĩ rằng có thể với hệ thống mặc định. Tôi nghĩ rằng người ta sẽ phải tạo một [CustomTool] (http://www.google.com/search?q=visual+studio+custom+tool) để phân tích một tệp nguồn mà sau đó sẽ tạo ra một tệp dữ liệu thiết kế khác. Điều này sẽ ngăn chặn phải gõ lại, nhưng tệp được tạo kết quả sẽ vẫn chứa toàn bộ dữ liệu (không phải là "tham chiếu" đến dữ liệu khác). –

+0

Vì vậy, về cơ bản tôi cần phải biến điều này thành một gợi ý trong Microsoft Connect? –

+0

.lưu ý rằng VS2011 đang ở chế độ xem trước dev và Blend 5 ở giai đoạn tương tự, vì vậy nếu chúng không hỗ trợ, tôi không thấy trước việc triển khai tính năng này ... –

Trả lời

0

Trong một số trường hợp này rất dễ dàng, những đòi hỏi:

  1. Thuộc tính bộ sưu tập là các loại IEnumerable hoặc IList (không phải là một lớp thực hiện nó)
  2. Khách sạn có một setter.

ví dụ: public IEnumerable Employees { get; set; }

Trước tiên, bạn trích xuất các mục vào từ điển tài nguyên, ví dụ:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:obj="clr-namespace:Test.Objects"> 
    <x:Array x:Key="SampleEmps" Type="obj:Employee"> 
     <obj:Employee Name="Skeet" Occupation="Programmer" /> 
     <obj:Employee Name="Skeet" Occupation="Programmer" /> 
     <obj:Employee Name="Dimitrov" Occupation="Programmer" /> 
    </x:Array> 
</ResourceDictionary> 

Sau đó, bạn thêm điều đó vào MergedDictionary của điều khiển sẽ chứa Chế độ xem. ví dụ.

<Window.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="Objects/SampleData.xaml" /> 
     </ResourceDictionary.MergedDictionaries> 
     <!-- ... --> 

Sau đó, bạn có thể tham khảo bộ sưu tập sử dụng StaticResource:

<obj:SomeOtherViewModel Employees="{StaticResource SampleEmps}"/> 

Bây giờ vấn đề với bộ sưu tập đặc biệt là bạn không thể chỉ đơn giản là tạo chúng trong XAML. Và vấn đề với một setter mất tích là bạn không thể gán tài sản bằng cách sử dụng một StaticResource, vì vậy tôi nghĩ rằng một setter là luôn luôn cần thiết.

Nếu bạn có bộ sưu tập chuyên dụng, bạn có thể sử dụng MarkupExtension để tạo một phiên bản.

[ContentProperty("Items")] 
public class GenericCollectionFactoryExtension : MarkupExtension 
{ 
    public Type Type { get; set; } 
    public Type T { get; set; } 
    public IEnumerable Items { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     var genericType = Type.MakeGenericType(T); 
     var list = Activator.CreateInstance(genericType) as IList; 
     if (list == null) throw new Exception("Instance type does not implement IList"); 
     foreach (var item in Items) 
     { 
      list.Add(item); 
     } 
     return list; 
    } 
} 

Bạn có thể trực tiếp tạo ra ví dụ một ObservableCollection trong các tài nguyên hoặc bạn ống mảng thông qua phần mở rộng này ở nơi mà bạn cần các mục:

xmlns:om="clr-namespace:System.Collections.ObjectModel;assembly=System" 
<obj:SomeViewModel x:Key="SomeVM"> 
    <obj:SomeViewModel.Employees> 
     <me:GenericCollectionFactory Type="{x:Type om:ObservableCollection`1}" 
            T="{x:Type obj:Employee}"> 
      <StaticResource ResourceKey="SampleEmps" /> 
     </me:GenericCollectionFactory> 
    </obj:SomeViewModel.Employees> 
</obj:SomeViewModel> 

Các `1 ở cuối om:ObservableCollection là cần thiết vì loại này là chung chung.

+0

Tôi sẽ phải thử điều này khi tôi có cơ hội ... Mặc dù, nó có một chút mùi với nó. Tôi không thích ý tưởng phải có dữ liệu mẫu được tích hợp vào tài nguyên cửa sổ. –

+0

@ m-y: Bạn có thể mở rộng phần mở rộng đánh dấu ở trên hoặc tạo một tiện ích mở rộng khác để nhận tài nguyên khi đang di chuyển mà không có tham chiếu cứng đến từ điển tài nguyên trong mã khác. –

Các vấn đề liên quan