В некоторых случаях это просто, для этого требуется:
- Свойство коллекции имеет тип IEnumerable или IList (не класс, реализующий его)
- У свойства есть сеттер.
например. public IEnumerable Employees { get; set; }
Сначала вы извлекаете элементы в словарь ресурсов, например,
<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>
Затем вы добавляете это к MergedDictionary
элемента управления, который будет содержать ViewModels. например, * 1 016 *
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Objects/SampleData.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- ... -->
Затем вы можете ссылаться на коллекцию, используя StaticResource
:
<obj:SomeOtherViewModel Employees="{StaticResource SampleEmps}"/>
Теперь проблема со специализированными коллекциями в том, что вы не можете просто создать их в XAML. И проблема с отсутствующим установщиком состоит в том, что вы не можете назначить свойство с помощью StaticResource
, поэтому я думаю, что установщик всегда необходим.
Если у вас есть специализированная коллекция, вы можете использовать MarkupExtension
для создания экземпляра.
[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;
}
}
Вы можете либо непосредственно создать, например, ObservableCollection в ресурсах, либо передать массив через это расширение в место, где вам нужны элементы:
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>
`1
в конце om:ObservableCollection
необходимо, так как тип является общим.