Wpf DataTemplate 引用自身; DataContext (= null) 问题
Wpf DataTemplate referencing itself; DataContext (= null) issues
我有意见。在此视图中,我使用我的自定义控件 GrMenu。
<pages:PageBase>
<Grid>
<views:GrMenu x:Name="InsightsMenu" Menu="{Binding Insights}" SelectItemCommand="{Binding LoadInsightCommand}" SelectedMenuItem="{Binding SelectedInsight, Mode=TwoWay}"/>
</Grid>
</pages:PageBase>
GrMenu 基本上类似于树视图,但使用 ItemsControls 实现。
<UserControl x:Name="GrMenuUserControl" x:Class="Views.GrMenu">
<UserControl.Resources>
<telerik:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<telerik:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter"/>
<converters:BoolToColourConverter x:Key="BoolToColourConverter" />
<DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type groupingMenu:IMenuItem}">
<Grid>
<telerik:RadExpander HorizontalAlignment="Left" VerticalAlignment="Top" Visibility="{Binding HasChildren, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<telerik:RadExpander.Header>
<Label Content="{Binding Header}" />
</telerik:RadExpander.Header>
<TextBlock>
<InlineUIContainer>
<ItemsControl ItemsSource="{Binding Children}" ItemTemplate="{DynamicResource MenuItemTemplate}" Margin="20,0,0,0"/>
</InlineUIContainer>
</TextBlock>
</telerik:RadExpander>
<Button
Visibility="{Binding HasChildren, Converter={StaticResource InvertedBooleanToVisibilityConverter}, Mode=OneWay}"
Content="{Binding Header}"
MinWidth="200"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Margin="20,2,2,2"
BorderThickness="0"
Click="MenuItemButton_OnClick"
Tag="{Binding Id}"
Command="{Binding SelectItemCommand, ElementName=GrMenuUserControl}"
CommandParameter="{Binding .}"
Background="{Binding IsSelected, Converter={StaticResource BoolToColourConverter}}"
/>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=GrMenuUserControl}">
<ItemsControl x:Name="GroupedMenuItems" ItemsSource="{Binding Menu.GroupedMenuItems}" ItemTemplate="{DynamicResource MenuItemTemplate}"/>
</Grid>
</UserControl>
我的页面基础(触发异常的 class)看起来像这样:
public abstract class PageBase : Page
{
protected PageBase()
{
Unloaded += Page_Unloaded;
}
public void Page_Unloaded(object sender, RoutedEventArgs e)
{
if(DataContext!=null)
DataContext = null;
}
}
事情是这样的。当我导航到我的屏幕然后离开时,我正在调用 Page_Unloaded 方法,该方法试图将 null 分配给 DataContext 但没有说:
Unable to cast object of type 'System.Windows.Controls.ControlTemplate' to type 'System.Windows.DataTemplate'.
我发现问题与这一行有关:
<InlineUIContainer>
<ItemsControl ItemsSource="{Binding Children}" ItemTemplate="{DynamicResource MenuItemTemplate}" Margin="20,0,0,0"/>
</InlineUIContainer>
就好像我只去掉了 ItemTemplate 属性一样一切正常,但是我失去了数据模板递归权限。
你们知道我可以使用的任何解决方法吗?
好的,我找到问题所在了。太傻了!
我为使其正常工作所做的唯一更改是我的数据模板的 x:Key 属性值。我猜这是一个被禁止的名字什么的..
新的解决方案:
<DataTemplate x:Key="MenuItemDataTemplate">
<InlineUIContainer>
<ItemsControl ItemsSource="{Binding Children}" ItemTemplate="{DynamicResource MenuItemDataTemplate}" Margin="20,0,0,0"/>
</InlineUIContainer>
<ItemsControl x:Name="GroupedMenuItems" ItemsSource="{Binding Menu.GroupedMenuItems}" ItemTemplate="{DynamicResource MenuItemDataTemplate}"/>
我有意见。在此视图中,我使用我的自定义控件 GrMenu。
<pages:PageBase>
<Grid>
<views:GrMenu x:Name="InsightsMenu" Menu="{Binding Insights}" SelectItemCommand="{Binding LoadInsightCommand}" SelectedMenuItem="{Binding SelectedInsight, Mode=TwoWay}"/>
</Grid>
</pages:PageBase>
GrMenu 基本上类似于树视图,但使用 ItemsControls 实现。
<UserControl x:Name="GrMenuUserControl" x:Class="Views.GrMenu">
<UserControl.Resources>
<telerik:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<telerik:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter"/>
<converters:BoolToColourConverter x:Key="BoolToColourConverter" />
<DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type groupingMenu:IMenuItem}">
<Grid>
<telerik:RadExpander HorizontalAlignment="Left" VerticalAlignment="Top" Visibility="{Binding HasChildren, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}">
<telerik:RadExpander.Header>
<Label Content="{Binding Header}" />
</telerik:RadExpander.Header>
<TextBlock>
<InlineUIContainer>
<ItemsControl ItemsSource="{Binding Children}" ItemTemplate="{DynamicResource MenuItemTemplate}" Margin="20,0,0,0"/>
</InlineUIContainer>
</TextBlock>
</telerik:RadExpander>
<Button
Visibility="{Binding HasChildren, Converter={StaticResource InvertedBooleanToVisibilityConverter}, Mode=OneWay}"
Content="{Binding Header}"
MinWidth="200"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Margin="20,2,2,2"
BorderThickness="0"
Click="MenuItemButton_OnClick"
Tag="{Binding Id}"
Command="{Binding SelectItemCommand, ElementName=GrMenuUserControl}"
CommandParameter="{Binding .}"
Background="{Binding IsSelected, Converter={StaticResource BoolToColourConverter}}"
/>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=GrMenuUserControl}">
<ItemsControl x:Name="GroupedMenuItems" ItemsSource="{Binding Menu.GroupedMenuItems}" ItemTemplate="{DynamicResource MenuItemTemplate}"/>
</Grid>
</UserControl>
我的页面基础(触发异常的 class)看起来像这样:
public abstract class PageBase : Page
{
protected PageBase()
{
Unloaded += Page_Unloaded;
}
public void Page_Unloaded(object sender, RoutedEventArgs e)
{
if(DataContext!=null)
DataContext = null;
}
}
事情是这样的。当我导航到我的屏幕然后离开时,我正在调用 Page_Unloaded 方法,该方法试图将 null 分配给 DataContext 但没有说:
Unable to cast object of type 'System.Windows.Controls.ControlTemplate' to type 'System.Windows.DataTemplate'.
我发现问题与这一行有关:
<InlineUIContainer>
<ItemsControl ItemsSource="{Binding Children}" ItemTemplate="{DynamicResource MenuItemTemplate}" Margin="20,0,0,0"/>
</InlineUIContainer>
就好像我只去掉了 ItemTemplate 属性一样一切正常,但是我失去了数据模板递归权限。
你们知道我可以使用的任何解决方法吗?
好的,我找到问题所在了。太傻了!
我为使其正常工作所做的唯一更改是我的数据模板的 x:Key 属性值。我猜这是一个被禁止的名字什么的..
新的解决方案:
<DataTemplate x:Key="MenuItemDataTemplate">
<InlineUIContainer>
<ItemsControl ItemsSource="{Binding Children}" ItemTemplate="{DynamicResource MenuItemDataTemplate}" Margin="20,0,0,0"/>
</InlineUIContainer>
<ItemsControl x:Name="GroupedMenuItems" ItemsSource="{Binding Menu.GroupedMenuItems}" ItemTemplate="{DynamicResource MenuItemDataTemplate}"/>