2011-11-22 7 views
5

que tienen los siguientes datos de la muestra, lo que da muy bien ...¿Reutilizar datos de diseño en 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> 

Sin embargo, me parece que sería útil para poder volver a utilizar esa lista de los empleados de la muestra en lugar de volver a escribir cada vez. No puedo entender cómo reutilizar esa lista. Básicamente, quiero tener otro archivo SampleData (SampleEmployees.xaml), que contiene la lista de los empleados, a continuación, ser capaz de incluir que en mis otras muestras ...

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

Además, la forma de crear la lista por separado en otro archivo XAML?

modelo de vista:

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

No creo que sea posible con el sistema predeterminado. Creo que uno debería crear una [CustomTool] (http://www.google.com/search?q=visual+studio+custom+tool) para analizar un archivo fuente que luego generaría otro archivo de datos de diseño. Esto evitaría tener que volver a escribir, pero el archivo generado resultante aún contendría la información completa (no una "referencia" a otros datos). –

+0

Entonces, básicamente, ¿debo convertir esto en una sugerencia en Microsoft Connect? –

+0

ir por eso.tenga en cuenta que VS2011 está en la vista previa de desarrollo, y Blend 5 se encuentra en una etapa similar, por lo que si aún no lo admiten, no preveo que implementen esta función ... –

Respuesta

0

En algunos casos esto es fácil, los que requieren:

  1. La propiedad de colección es de tipo IEnumerable o IList (no una clase implementarlo)
  2. La propiedad tiene un colocador.

e.g. public IEnumerable Employees { get; set; }

Primero extrae los elementos en un diccionario de recursos, p.

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

A continuación, añadir que a la MergedDictionary de un control que contendrá los ViewModels. p.ej.

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

Entonces, podrá hacer referencia usando la colección StaticResource:

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

Ahora el problema con colecciones especializadas es que no se puede simplemente crearlas en XAML. Y el problema con un setter perdido es que no puede asignar la propiedad usando un StaticResource, por lo que creo que un setter siempre es necesario.

Si tiene una colección especializada, puede usar un MarkupExtension para crear una instancia.

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

Puede crear ya sea directamente, por ejemplo, un ObservableCollection en los recursos o tubo de la matriz a través de esta extensión en el lugar donde se necesitan los artículos:

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> 

El `1 al final de om:ObservableCollection es necesario ya que el tipo es genérico.

+0

Voy a tener que probar esto cuando tenga la oportunidad ... Sin embargo, tiene un poco de olor. No me gusta la idea de tener que tener mis datos de muestra integrados en los recursos de la ventana. –

+0

@ m-y: Puede extender la extensión de marcado arriba o crear otra que obtenga los recursos sobre la marcha sin una referencia difícil al diccionario de recursos en el otro código. –

Cuestiones relacionadas