简体   繁体   中英

Why is the ListBox ItemTemplateSelector=“{StaticResource MyDataTemplateSelector}” not working with the resource?

Subject: I'm learning the DataTemplate concept by using a Microsoft example found here: https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview and on GitHub here: https://github.com/Microsoft/WPF-Samples/tree/master/Data%20Binding/DataTemplatingIntro

Issue: Xaml Design window displays error.

Error: NullReferenceException: Object reference not set to an instance of an object.

And from the top of the stack at the exception:

at BindingTest.TaskListDataTemplateSelector.SelectTemplate(Object item, DependencyObject container)

Specifics: Error appears after creating class TaskListDataTemplateSelector and adding these two lines:

<Window.Resources>

    <local:TaskListDataTemplateSelector x:Key="MyDataTemplateSelector"/>

</Window.Resources>

and

<ListBox ....

   ItemTemplateSelector="{StaticResource MyDataTemplateSelector}"

</ListBox>

Further info: The example from Microsoft has the same issue.

Window x:Class="BindingTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:BindingTest"
    mc:Ignorable="d"
    Title="MainWindow"  Width="525" SizeToContent="WidthAndHeight">

<Window.Resources>
    <local:Tasks x:Key="myTodoList"/>
    <local:TaskListDataTemplateSelector x:Key="MyDataTemplateSelector"/>

    <DataTemplate x:Key="importantTaskTemplate">
        <DataTemplate.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="20"/>
            </Style>
        </DataTemplate.Resources>
        <Border Name="border" BorderBrush="Red" BorderThickness="1"
                Padding="5" Margin="5">
            <DockPanel HorizontalAlignment="Center">
                <TextBlock Text="{Binding Path=Description}"/>
                <TextBlock>!</TextBlock>
            </DockPanel>
        </Border>
    </DataTemplate>

    <DataTemplate x:Key="myTaskTemplate">
        <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
               Padding="5" Margin="5">
            <Grid ShowGridLines="false">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0"  Text="Task Name:"/>
                <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=Name}"/>
                <TextBlock Grid.Row="1" Grid.Column="0"  Text="Description:"/>
                <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
                <TextBlock Grid.Row="2" Grid.Column="0"  Text="Priority:"/>
                <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
            </Grid>
        </Border>

        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=TaskType}">
                <DataTrigger.Value>
                    <local:TaskType>Home</local:TaskType>
                </DataTrigger.Value>
                <Setter TargetName="border" Property="BorderBrush" Value="Yellow"/>
            </DataTrigger>
        </DataTemplate.Triggers>

    </DataTemplate>
</Window.Resources>

<Grid>
    <StackPanel>
        <TextBlock FontSize="20" Text="My Task List"/>

        <ListBox Width="400" Margin="10"
                 ItemsSource="{Binding Source={StaticResource myTodoList}}"
                 ItemTemplateSelector="{StaticResource MyDataTemplateSelector}"
                   HorizontalContentAlignment="Stretch">
        </ListBox>
    </StackPanel>

</Grid>

 public   class TaskListDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate
      SelectTemplate(object item, DependencyObject container)
    {
        if (item != null && item is Task)
        {
            var taskitem = (Task)item;
            var window = Application.Current.MainWindow;
            if (taskitem.Priority == 1)
                return
                    window.FindResource("ImportantTaskTemplate") as DataTemplate;
            return
                window.FindResource("MyTaskTemplate") as DataTemplate;
        }

        return null;
    }
}

I found an error. It was a spelling issue: specifically capitalization.

The spelling of MyTaskTemplate and ImportantTaskTemplate were not consistent throughout the project.

The project now compiles and runs but still getting same exception in the Xaml Design window.

More digging revealed the fix for the Null Reference Exception error in the Xaml design window. Thanks to Chris Anderson and his book: Essential Windows Presentation Foundation page 341. Replaced TaskListDataTemplateSelector with this:

 public class TaskListDataTemplateSelector : DataTemplateSelector
{

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item != null && item is Task)
        {
            var taskitem = (Task)item;
            var window = Application.Current.MainWindow;
            if (taskitem.Priority == 1)
                return ((FrameworkElement)container).FindResource
                    ("ImportantTaskTemplate") as DataTemplate;

            return
            ((FrameworkElement)container).FindResource
                    ("MyTaskTemplate") as DataTemplate;
        }
        return null;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM