На данный вопрос уже ответили:
Каким образом можно в главном окне подсовывать нужный UserControl
без изменения параметра видимости. К примеру есть окно при запуске отображается FirstUserControl
потом при каком нибудь событие (например нажатие на кнопку) FirstUcerControl
отрабатывает (закрывается), и отображается новый SecondUserControl
.
Для этого используется DataTemplateSelector
. Я покажу небольшой пример.
Допустим, у меня есть VM-классы CarVm
и UserVm
, которые я хочу отображать в одном окне, я набросал такую простую MainVm
:
class MainVm : Vm
{
object innerVm;
public object InnerVm
{
get => innerVm;
set => Set(ref innerVm, value, nameof(InnerVm));
}
public DelegateCommand ChangeCommand { get; }
public MainVm()
{
ChangeCommand = new DelegateCommand(_ => InnerVm = (InnerVm is UserVm) ? (object)new CarVm() : (object)new UserVm());
}
}
Тут всё просто, по команде у нас меняется свойство InnerVm
, причем оно каждый раз будет менять тип.
Займемся разметкой, я в Grid
добавлю ContentPresenter
для отображения InnerVm
и кнопку для вызова команды:
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentPresenter Content="{Binding InnerVm}">
</ContentPresenter>
<Button Grid.Row="1" Content="Change"
HorizontalAlignment="Center"
Command="{Binding ChangeCommand}"/>
</Grid>
Теперь нам для каждого отображаемого типа необходимо реализовать DataTemplate-разметку, я добавлю ее в ресурсы ContentPresenter
:
<ContentPresenter.Resources>
<DataTemplate x:Key="UserTemplate">
<StackPanel d:DataContext="{d:DesignInstance Type=c:UserVm}">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Age}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CarTemplate">
<StackPanel d:DataContext="{d:DesignInstance Type=c:CarVm}">
<TextBlock Text="{Binding Model}"/>
<TextBlock Text="{Binding MaxSpeed}"/>
</StackPanel>
</DataTemplate>
</ContentPresenter.Resources>
Теперь пишем класс-наследник DataTemplateSelector
:
class MyTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var fe = (FrameworkElement)container;
if (item is UserVm) return fe.FindResource("UserTemplate") as DataTemplate;
if (item is CarVm) return fe.FindResource("CarTemplate") as DataTemplate;
return null;
}
}
Создаем экземпляр этого класса в ресурсах Grid
:
<Grid.Resources>
<c:MyTemplateSelector x:Key="MyTemplateSelector"/>
</Grid.Resources>
И подключаем его к нашему ContentPresenter
: ContentTemplateSelector="{StaticResource MyTemplateSelector}"
Готово!
На клиенте в браузере выводятся изображения фотографий небольших размеров, например, 20 штук в формате :