2011-11-22 10 views
5

Ho i seguenti dati di esempio, che funziona bene ...Riutilizzare i dati di progettazione in 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> 

Tuttavia, ritengo che sarebbe utile essere in grado di riutilizzare quella lista dei dipendenti del campione, invece di ridigitare ogni volta. Non riesco a capire come riutilizzare quella lista. Fondamentalmente, voglio avere un altro file SampleData (SampleEmployees.xaml) che contiene tale elenco dei dipendenti, quindi in grado di comprendere che nei miei altri campioni ...

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

Inoltre, come per creare l'elenco separatamente in un altro file XAML ??

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

Non penso sia possibile con il sistema predefinito. Penso che si dovrebbe creare un [CustomTool] (http://www.google.com/search?q=visual+studio+custom+tool) per analizzare un file sorgente che poi genererebbe un altro file di dati di progetto. Ciò impedirebbe di dover ridigitare, ma il file generato risultante conterrebbe comunque i dati completi (non un "riferimento" ad altri dati). –

+0

Quindi in pratica ho bisogno di trasformarlo in un suggerimento in Microsoft Connect? –

+0

provaci.nota che VS2011 è in anteprima di sviluppo e Blend 5 è in una fase simile, quindi se non lo supportano ancora non prevedo che implementino questa funzione ... –

risposta

0

In alcuni casi questo è facile, quelli richiedono:

  1. La proprietà raccolta è di tipo IEnumerable o IList (non una classe attuazione)
  2. La proprietà ha un setter.

ad es. public IEnumerable Employees { get; set; }

Prima di estrarre gli elementi in un dizionario di risorse, ad es.

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

Quindi aggiunge che al MergedDictionary di un controllo che conterrà i ViewModel. per esempio.

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

Quindi è possibile quindi fare riferimento alla raccolta utilizzando StaticResource:

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

Ora il problema con le collezioni specializzate è che non si può semplicemente creare in XAML. E il problema con un setter mancante è che non è possibile assegnare la proprietà utilizzando un StaticResource, quindi penso che un setter sia sempre necessario.

Se si dispone di una raccolta specializzata, è possibile utilizzare uno MarkupExtension per creare un'istanza.

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

È possibile creare direttamente ad esempio ObservableCollection nelle risorse o si reindirizza la matrice attraverso questa estensione nel luogo in cui avete bisogno degli articoli:

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> 

Il `1 alla fine di om:ObservableCollection è necessario in quanto il tipo è generico.

+0

Dovrò provare questo quando ne avrò la possibilità ... Tuttavia, ha un po 'di odore. Non mi piace l'idea di dover incorporare i miei dati di esempio nelle risorse della finestra. –

+0

@ m-y: è possibile estendere l'estensione di markup in alto o crearne un'altra che raccolga le risorse al volo senza un riferimento rigido al dizionario delle risorse nell'altro codice. –

Problemi correlati