Типизированные шаблоны данных в Silverlight - PullRequest
1 голос
/ 26 октября 2010

Насколько я понимаю, Silverlight не поддерживает шаблоны данных с атрибутом DataType.

Как бы вы достигли следующего в SL (автор Джош Смит, полная ссылка ниже). В двух словах, он говорит, что если вы связываете вкладки TabControl с коллекцией ViewModels, WPF выяснит, как отображать каждую из них на лету, ища DataTemplate, у которого есть соответствующий (соответствующий) набор DataType. Круто, но мне интересно, как бы вы (могли?) Сделать это в Silverlight.

Применение представления к модели представления

MainWindowViewModel косвенно добавляет и удаляет WorkspaceViewModel объекты в и из главного окна TabControl. Полагаясь на данные обязательный, свойство Content TabItem получает Производный от ViewModelBase объект для дисплей. ViewModelBase не является пользовательским интерфейсом элемент, поэтому он не имеет внутренней поддержки для рендеринга себя. По умолчанию в WPF невизуальный объект отображается отображение результатов звонка его метод ToString в TextBlock. Это явно не то, что вам нужно, если ваши пользователи не горят желание увидеть имя типа нашего Классы ViewModel!

Вы можете легко сказать WPF, как визуализировать объект ViewModel с использованием типизированного DataTemplates. Типизированный DataTemplate не назначено значение x: Key к нему, но у него есть свой тип данных свойство установлено на экземпляр Тип класс. Если WPF пытается сделать один из ваших объектов ViewModel, это будет проверить, если система ресурсов имеет типизированный DataTemplate в области видимости чей DataType такой же как (или базовый класс) тип вашего Объект ViewModel. Если он найдет один, он использует этот шаблон для рендеринга Объект ViewModel, на который ссылается вкладка Свойство содержимого элемента.

Файл MainWindowResources.xaml имеет ResourceDictionary. Этот словарь добавляется в ресурс главного окна иерархия, что означает, что ресурсы, которые он содержит, находятся в объем ресурса окна. Когда вкладка содержимое элемента установлено на ViewModel объект, типизированный DataTemplate из этого словарь предоставляет представление (то есть пользовательский элемент управления), чтобы отобразить его, как показано на рисунке 10. на рисунке 10.

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx на рисунке 10.

1 Ответ

1 голос
/ 29 октября 2010

Вот ОДИН способ, которым вы можете сделать это.Я использовал такую ​​технику в прошлом и имел большой успех с ней.

Рассмотрим очень простой контейнер, который создаст для вас представление следующим образом:

public class ViewMapper : ContentControl
{
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);

        if (e.Property.Name == "DataContext")
            WhenDataContextChanges();
    }

    private void WhenDataContextChanges()
    {
        if (DataContext == null)
            Content = null;
        else
            Content = ViewFactory.GetView(DataContext.GetType());
    }
}

РЕДАКТИРОВАТЬ

Итак, вы можете использовать этот элемент управления, чтобы сделать отображение для вас:

<Border DataContext="{Binding MyViewModel}">
    <ViewMapper />
</Border>

КОНЕЦ РЕДАКТИРОВАНИЯ

Обратите внимание, чтоViewMapper просто ожидает изменения контекста данных, ищет подходящее представление для типа данных и создает новое.Он основан на ViewFactory, который является очень простым статическим поиском, который сопоставляет типы с представлениями:

public class ViewFactory
{
    private static readonly Dictionary<string, Func<UIElement>> _registry = new Dictionary<string, Func<UIElement>>();

    private static string Key(Type viewModelType)
    {
        return viewModelType.FullName;
    }

    public static void RegisterView(Type viewModelType, Func<UIElement> createView)
    {
        _registry.Add(Key(viewModelType), createView);
    }

    public static UIElement GetView(Type viewModelType)
    {
        var key = Key(viewModelType);
        if (!_registry.ContainsKey(key))
            return null;

        return _registry[key]();
    }
}

Затем вам просто нужно зарегистрировать отображения представлений в каком-то месте:

ViewFactory.RegisterView(typeof(SomeViewModel), () => new SomeView());

Примечаниетот ViewFactory мог бы так же легко использовать Activator.CreateInstance вместо использования механизма Func.Сделайте этот шаг еще дальше, и вы сможете использовать контейнер IoC ... Вы всегда можете выбрать отображение через строковое свойство Name в ViewModel вместо типа ... возможности здесь бесконечны и мощны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...