ItemContainerStyleSelector causes binding errors

2019-07-27 07:40发布

问题:

I have two object types, for simplicity I will call them Category and Product. A category may have sub-categories, as well as products. Products do not contain other objects- they are leaves in the tree.

public class Product
{
    public string Name {get; set;}
}

public class Category
{
    public IEnumerable<object> Children
    {
        //return a mixed set of categories and products
    }

    public bool IsExpanded {get; set;}

    public bool IsHighlighted {get; set;}
}

I want to display them in a TreeView, in the exact way they appear in the object graph. e.g.

Category 1
    Product
    Category 1.1
    Category 1.2
        Product
    Product
Category 2
    Category 2.1
        Category 2.1.1
    Product

and so on. My XAML is

<UserControl xmlns:.....>
<UserControl.Resources>
    <Style x:Key="CategoryStyle" TargetType="TreeViewItem">
        <Setter Property="IsExpanded" Value="{Binding IsExpanded ,Mode=TwoWay}"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsHighlighted}" Value="True">
                <Setter Property="FontWeight" Value="Bold"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
    <local:TreeItemStyleSelector x:Key="TreeItemStyleSelector" />
</UserControl.Resources>

<Grid>
    <TreeView ItemContainerStyleSelector="{StaticResource TreeItemStyleSelector}">
    <!-- ItemContainerStyleSelector causes binding errors-->
        <TreeView.Resources>
            <!-- template for products -->
            <DataTemplate DataType="{x:Type local:Product}">
                <Button Content="{Binding Name}" Style="{StaticResource ButtonStyle}"/>
            </DataTemplate>
            <!-- template for categories -->
            <HierarchicalDataTemplate DataType="{x:Type local:Category}" ItemsSource="{Binding Children}">
                <StackPanel Orientation="Horizontal">
                    <!-- template omitted here -->
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</Grid>
</UserControl>

The tree renders correctly, but I get a lot of binding errors in the output window, saying that Product has no properties named Children, IsExpanded and IsHighlighted. It seems that WPF tries to apply the HierarchicalDataTemplate on Products.
Interesting, but when I remove the ItemContainerStyleSelector no binding errors are raised. The selector code is rather simple

public class TreeItemStyleSelector : StyleSelector
{
    public override System.Windows.Style SelectStyle(object item, DependencyObject container)
    {
        if(item is Category)
        {
            return (System.Windows.Style)((FrameworkElement)container).FindResource("CategoryStyle");
        }
        return null;
    }
}

How can I prevent the errors from being raised?
Any help will be greatly appreciated.