Вот ОДИН способ, которым вы можете сделать это.Я использовал такую технику в прошлом и имел большой успех с ней.
Рассмотрим очень простой контейнер, который создаст для вас представление следующим образом:
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 вместо типа ... возможности здесь бесконечны и мощны.