在WPF用户控件中使用数据模板选择器时抛出Null Reference Exception异常

3

您好,我遇到了一个问题,在使用数据模板选择器的用户控件的xaml中抛出了空引用异常,但我不确定原因。以下是代码,请帮助解决问题。

更新:只在设计时发生,而非运行时。

数据模板选择器代码:

using System.Windows;
using System.Windows.Controls;
using UI.ViewModel;

namespace UI.DataTemplateSelectors
{
    public class CouponViewerDataTemplateSelector : DataTemplateSelector
    {
        public DataTemplate coupon1DataTemplateSelector { get; set; }
        public DataTemplate coupon2DataTemplateSelector { get; set; }
        public DataTemplate coupon3DataTemplateSelector { get; set; }



        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item == null)
                return null;
            var CouponViewerViewModel = (CouponViewerViewModel)item;
            switch (CouponViewerViewModel.Coupon.CouponBarcode )
            {

                case "994460":
                    return Coupon1DataTemplateSelector;
                case "994470":
                    return Coupon2DataTemplateSelector;
                case "994480":
                    return Coupon3DataTemplateSelector;


            }
            return null;
        }


    }
}

Xaml(我已将不同DataTemplates代码折叠,因为xaml文件非常庞大)

<UserControl x:Class="UI.View.CouponViewerView"
        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:viewModel="clr-namespace:UI.ViewModel"
        xmlns:converter="clr-namespace:UI.View.Converter"
        xmlns:converters="clr-namespace:UI.Converters"
        xmlns:Web="clr-namespace:Web;assembly=Web"
        xmlns:dataTemplateSelectors="clr-namespace:UI.DataTemplateSelectors"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance Type=viewModel:CouponViewerViewModel, IsDesignTimeCreatable=True}"


        Height="1018" Width="720">
    <UserControl.Resources>
        <converter:EmptyStringToVisibilityConverter x:Key="EmptyStringToVisibilityConverter"/>
        <converters:AppendCharToBeginningAndEndOfStringConverter x:Key="AppendCharToBeginningAndEndOfStringConverter"/>
        <converters:HexToBackgroundColourConverter x:Key="HexToBackgroundColourConverter"/>
        <converters:HexToForegroundColourConverter x:Key="HexToForegroundColourConverter"/>
        <converters:MaxCharcterSelectionNameConverter x:Key="MaxCharcterSelectionNameConverter"/>
        <converters:DateTimeToSplitDataGridConverter x:Key="DateTimeToSplitDataGridConverter"/>
        <converters:HeaderFormatterConverter x:Key="HeaderFormatterConverter"/>

            <DataTemplate x:Key="Coupon1DataTemplateSelector" ...>

            <DataTemplate x:Key="Coupon2DataTemplateSelector" ...>

            <DataTemplate x:Key="Coupon3DataTemplateSelector" ...>

                 <dataTemplateSelectors:CouponViewerDataTemplateSelector

        Coupon1DataTemplateSelector="{StaticResource Coupon1DataTemplateSelector}"
        Coupon2DataTemplateSelector="{StaticResource Coupon2DataTemplateSelector}"
        Coupon3DataTemplateSelector ="{StaticResource Coupon3DataTemplateSelector}"
        x:Key="CouponViewerDataTemplateSelector" />

</UserControl.Resources>

 <StackPanel>
        <StackPanel x:Name="StackPanelToPrint">
            <StackPanel.ContextMenu >
                <ContextMenu>
                    <MenuItem Header="Print"  Click="PrintCurrentForm" />
                    <MenuItem Header="OverLay Image"  Command="{Binding Path=OverlayImageToCouponViewerCommand }" />
                </ContextMenu>
            </StackPanel.ContextMenu>

            <Grid Margin="0,0,0,0">

                <TextBlock Text="{Binding DesignTimeError}" Visibility="{Binding DesignTimeError, Converter={StaticResource EmptyStringToVisibilityConverter}}" Grid.ColumnSpan="2" Margin="0,0,0,34" />
                <Canvas Grid.ColumnSpan="2" Margin="0,0,0,0">
                    <Rectangle Fill="Black" Width="8.5" Height="8.5" Canvas.Left="11" Canvas.Top="128" />
                    <Rectangle Fill="Black" Width="8.5" Height="8.5" Canvas.Left="742.5" Canvas.Top="128" />
                    <TextBlock Canvas.Left="338" FontSize="9" Foreground="Red" Canvas.Top="1046"  Text="{Binding Path=MarkSenseCoupon.CouponBarcode}" />
                    <TextBlock FontFamily="Free 3 Of 9"  Canvas.Left="24"  Canvas.Top="1026" FontSize="110" Height="15" Text="{Binding Path=Coupon.CouponBarcode,  Converter={StaticResource AppendCharToBeginningAndEndOfStringConverter}}"/>
                    <TextBlock Canvas.Left="409" FontSize="9" Foreground="Red"  Canvas.Top="1046" Text="{Binding Path=MarkSenseCoupon.CouponInstance}" />
                    <TextBlock FontFamily="Free 3 of 9" Canvas.Left="409" Canvas.Top="1026"  FontSize="110" Height="15" Text="{Binding Path=Coupon.CouponInstance,  Converter={StaticResource AppendCharToBeginningAndEndOfStringConverter}}"/>
                    <Rectangle Fill="Black" Width="8.5" Height="8.5" Canvas.Left="11.5" Canvas.Top="1043" />
                    <Rectangle Fill="Black" Width="8.5" Height="8.5" Canvas.Left="742.5" Canvas.Top="1043" />



                </Canvas>

                <Image Canvas.ZIndex="1" Source="{Binding Coupon.OverlayImage}"  Margin="0,-21,-76,108" Stretch="Fill" x:Name="PrintImageContextMenu" />




                <StackPanel Margin="-105,146,66,0" Height="900" VerticalAlignment="Top" >

                    <ContentControl Content="{Binding}"  ContentTemplateSelector="{StaticResource CouponViewerDataTemplateSelector}"  />


                </StackPanel>

            </Grid>
        </StackPanel>

    </StackPanel>

</UserControl>

堆栈跟踪:

    at UI.DataTemplateSelectors.CouponViewerDataTemplateSelector.SelectTemplate(Object item, DependencyObject container)
   at System.Windows.Controls.ContentPresenter.ChooseTemplate()
   at System.Windows.Controls.ContentPresenter.EnsureTemplate()
   at System.Windows.Controls.ContentPresenter.OnPreApplyTemplate()
   at System.Windows.FrameworkElement.ApplyTemplate()
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.UIElement.UpdateLayout()

这是一个“猜测行”游戏吗?顺便问一下,你在调试器中检查了哪种类型的项目? - JeffRSon
好的,我找到了发生错误的代码行,就在添加内容控件的地方:``我的问题是,直到我添加Coupon3DataTemplateSelector之前它都是工作正常的。然而,里面的XAML与Coupon1DataTemplateSelector完全相同,这让我感到困惑,不知为何会出现这种情况。 - philmckendry
1
尝试将 case "994480" 替换为 default。同时,任何关于设计时或运行时的信息都应该在问题本身中提供。您可能需要在选择器内放置一个 MessageBox 来调试设计时问题。 - JeffRSon
如果在设计时执行的代码中包含了MessageBox,它将会出现。只需在您的ViewModel构造函数中尝试即可。 - JeffRSon
显示剩余4条评论
2个回答

1

在我之前工作的同事在ViewModel中添加了这行代码,而我没有注意到,导致所有问题都是由于它在设计时数据加载之前返回所造成的。

    public CouponViewerViewModel()
    {

        if (DesignerProperties.IsInDesignMode == true)
        {
            return;
        }
        if (DesignerProperties.IsInDesignMode)
        {
            LoadDesignTimeData();
        }

    }

最后一个问题非常愚蠢,敬请谅解。


顺便说一句,将bool值与truefalse进行比较是没有意义的 - 要么使用原始的bool值,要么取反。告诉你的同事这个消息吧... - JeffRSon

0

属性名称区分大小写。

public DataTemplate coupon1DataTemplateSelector { get; set; }

对比。

Coupon1DataTemplateSelector="{StaticResource Coupon1DataTemplateSelector}"

抱歉,我不得不修改我的代码来在这里提问,在代码中它们都是正确的大小写,我已经修改了问题以反映这一点。 - philmckendry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接