I'm Stuck creating a Master/Detail View in WinUI 3.
I Have a treeview as my master list with two different item types ExplorerItemTypeA and ExplorerItemTypeA each a partial class from the base ExplorerItem
I wish for the detail view to show the correct template for the different type (A&B) so I can bind and edit etc.
The Treeview DataTemplates work fine. Here is the XAML for the details view:
<Page.Resources>
<DataTemplate x:Key="ContentTypeATemplate" x:DataType="local:ExplorerItemTypeA">
<StackPanel Orientation="Horizontal">
<TextBlock Text="A Template"/>
<TextBlock Text="{x:Bind Name}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ContentTypeBTemplate" x:DataType="local:ExplorerItemTypeB">
<StackPanel Orientation="Horizontal">
<TextBlock Text="B Template"/>
<TextBlock Text="{x:Bind Name}"/>
</StackPanel>
</DataTemplate>
<ExplorerContentTemplateSelector x:Key="ExplorerContentTemplateSelector"
TreeItemTypeATemplate="{StaticResource ContentTypeATemplate}"
TreeItemTypeBTemplate="{StaticResource ContentTypeBTemplate}"/>
</Page.Resources>
If first tried a frame but am now trying a Content presenter for the detail view.
<TreeView x:Name="MasterListView"
Grid.Column="0"
ItemsSource="{x:Bind ViewModel.TemplateItems}"
SelectedItem="{x:Bind ViewModel.SelectedItem,Mode=TwoWay}"
ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}"/>
<ContentPresenter
x:Name="DetailContentPresenter"
Grid.Column="1"
Content="{x:Bind MasterListView.SelectedItem, Mode=OneWay}"
ContentTemplateSelector="{StaticResource ExplorerContentTemplateSelector}" />
The Selector is
public class ExplorerContentTemplateSelector : DataTemplateSelector
{
public DataTemplate TreeItemTypeATemplate { get; set; }
public DataTemplate TreeItemTypeBTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item)
{
var explorerItem = (ExplorerItem)item;
switch (explorerItem.Type)
{
case ExplorerItem.ExplorerItemType.A:
return TreeItemTypeATemplate;
case ExplorerItem.ExplorerItemType.B:
return TreeItemTypeBTemplate;
default:
Console.WriteLine("Default case");
return TreeItemTypeATemplate;
}
}
}
I feel the answer is obvious and elegant, but despite searching for clues and methods this c# beginner is just not getting anywhere. I've been stuck on this simple problem for far longer than I care to admit.
Thanks to anyone who is willing to give their time.
Replace the ContentPresenter
with a ContentControl
in your XAML markup:
<ContentControl
x:Name="DetailContentPresenter"
Grid.Column="1"
Content="{x:Bind MasterListView.SelectedItem, Mode=OneWay}"
ContentTemplateSelector="{StaticResource ExplorerContentTemplateSelector}" />
In your DataTemplateSelector
, you should also override the SelectTemplateCore
overload that accepts a DependencyObject
parameter:
public class ExplorerContentTemplateSelector : DataTemplateSelector
{
public DataTemplate TreeItemTypeATemplate { get; set; }
public DataTemplate TreeItemTypeBTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item) =>
SelectTemplateCore(item, null);
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var explorerItem = item as ExplorerItem;
switch (explorerItem?.Type)
{
case ExplorerItem.ExplorerItemType.A:
return TreeItemTypeATemplate;
case ExplorerItem.ExplorerItemType.B:
return TreeItemTypeBTemplate;
default:
Console.WriteLine("Default case");
return TreeItemTypeATemplate;
}
}
}