应用自定义列表框项的样式时,应用程序抛出异常

时间:2014-03-10 08:15:44

标签: wpf xaml windows-phone-8 listboxitem

我遇到了一个问题,需要一点时间。我需要在我的Windows phone 8应用程序的多个页面上添加列表框,在每个页面上,ListBoxItem的正常/选定背景是不同的(10-12页)。一个解决方案是我为每个ListBoxItem为我的样式表中的每个页面硬编码颜色代码创建不同的样式(我不想要)。所以我扩展了ListBoxItem类,并为ListboxItem的正常和选定项目背景添加了2个依赖项属性。所以我可以在每个xaml页面上设置这些属性,而不必为每个页面创建不同的样式。 这是我的扩展控件

public class CustomListboxItem : ListBoxItem
{
    public static readonly DependencyProperty NormalBackgroundProperty =
        DependencyProperty.Register("NormalBackground", typeof(SolidColorBrush), typeof(CustomListboxItem), new PropertyMetadata(null));
    public static readonly DependencyProperty SelectedBackgroundProperty =
        DependencyProperty.Register("SelectedBackground", typeof(SolidColorBrush), typeof(CustomListboxItem), new PropertyMetadata(null));
    public SolidColorBrush NormalBackground
    {
        get { return (SolidColorBrush)GetValue(NormalBackgroundProperty); }
        set { base.SetValue(NormalBackgroundProperty, value); }
    }
    public SolidColorBrush SelectedBackground
    {
        get { return (SolidColorBrush)GetValue(SelectedBackgroundProperty); }
        set { base.SetValue(SelectedBackgroundProperty, value); }
    }
}

以下是如何使用它(CyclesList只是字符串列表):

<ListBox Grid.Row="1" ItemsSource="{Binding CyclesList}" ItemContainerStyle="{StaticResource FilterListBoxItemStyle}" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <controls:CustomListboxItem NormalBackground="Transparent" Content="{Binding}" SelectedBackground="Red"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

以下是我申请使其成为通用的风格。

<Style x:Key="FilterListBoxItemStyle" TargetType="controls:CustomListboxItem">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Border x:Name="LayoutRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"/>
                            <VisualState x:Name="Disabled"/>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="SelectionStates">
                            <VisualState x:Name="Unselected"/>
                            <VisualState x:Name="Selected">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedBackground}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                    Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=NormalBackground}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

但是我的应用程序在这里抛出异常(完整堆栈跟踪):

  

{System.Windows.Markup.XamlParseException:[Line:0 Position:0] ---&gt; System.Windows.Markup.XamlParseException:[Line:0 Position:0] ---&gt; System.Windows.Markup.XamlParseException:[Line:0 Position:0] ---&gt; System.Windows.Markup.XamlParseException:[Line:0 Position:0] ---&gt; System.Windows.Markup.XamlParseException:[Line:0 Position:0] ---&gt; System.Windows.Markup.XamlParseException:[Line:0 Position:0] ---&gt; System.Windows.Markup.XamlParseException:[Line:0 Position:0]      在MS.Internal.XcpImports.CheckHResult(UInt32 hr)      在MS.Internal.XcpImports.SetValue(IManagedPeerBase obj,DependencyProperty属性,DependencyObject doh)      在System.Windows.DependencyObject.SetValue(DependencyProperty属性,DependencyObject doh)      在System.Windows.Controls.ListBox.GetContainerForItemOverride()      在System.Windows.Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.GetContainerForItem(Object item,DependencyObject recycledContainer)      在System.Windows.Controls.ItemContainerGenerator.Generator.GenerateNext(Boolean stopAtRealized,Boolean&amp; isNewlyRealized)      在System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives.IItemContainerGenerator.GenerateNext(Boolean&amp; isNewlyRealized)      在System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(大小约束)      在System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget,Double inWidth,Double inHeight,Double&amp; outWidth,Double&amp; outHeight)      ---内部异常堆栈跟踪结束---      在MS.Internal.XcpImports.CheckHResult(UInt32 hr)      在MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement元素,Size availableSize)      在System.Windows.Controls.ScrollContentPresenter.MeasureOverride(大小约束)      在System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget,Double inWidth,Double inHeight,Double&amp; outWidth,Double&amp; outHeight)      ---内部异常堆栈跟踪结束---      在MS.Internal.XcpImports.CheckHResult(UInt32 hr)      在MS.Internal.XcpImports.UIElement_Measure(UIElement元素,Size availableSize)      在System.Windows.UIElement.Measure(Size availableSize)      在System.Windows.Controls.ScrollViewer.MeasureOverride(大小约束)      在System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget,Double inWidth,Double inHeight,Double&amp; outWidth,Double&amp; outHeight)      ---内部异常堆栈跟踪结束---      在MS.Internal.XcpImports.CheckHResult(UInt32 hr)      在MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement元素,Size availableSize)      在System.Windows.FrameworkElement.MeasureOverride(Size availableSize)      在System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget,Double inWidth,Double inHeight,Double&amp; outWidth,Double&amp; outHeight)      ---内部异常堆栈跟踪结束---      在MS.Internal.XcpImports.CheckHResult(UInt32 hr)      在MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement元素,Size availableSize)      在System.Windows.FrameworkElement.MeasureOverride(Size availableSize)      在System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget,Double inWidth,Double inHeight,Double&amp; outWidth,Double&amp; outHeight)      ---内部异常堆栈跟踪结束---      在MS.Internal.XcpImports.CheckHResult(UInt32 hr)      在MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement元素,Size availableSize)      在Microsoft.Phone.Controls.PhoneApplicationFrame.MeasureOverride(Size availableSize)      在System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget,Double inWidth,Double inHeight,Double&amp; outWidth,Double&amp; outHeight)      ---内部异常堆栈跟踪结束---}

从Stack-Trace看,如果我缺少控件的宽度/高度,可能会出现,但我也尝试设置这些,但没有任何效果。我有什么问题吗?或者你能建议一个更好的方法来制作通用的CustomListBoxItem吗?

感谢您的期待,

的问候,

2 个答案:

答案 0 :(得分:2)

CustomListboxItem样式的资源字典键是FilterListBoxItemStyle

<Style x:Key="FilterListBoxItemStyle" TargetType="controls:CustomListboxItem">

但您使用FilterListBoxStyle来引用样式资源:

<ListBox ... ItemContainerStyle="{StaticResource FilterListBoxStyle}">

将上述声明更改为

<ListBox ... ItemContainerStyle="{StaticResource FilterListBoxItemStyle}">

<强>更新 话虽如此,还有另外一件事要提。为了拥有自定义派生的ListBoxItem类,您不能简单地在ItemTemplate中的DataTemplate中使用它。相反,您还可以创建一个自定义派生的ListBox类来覆盖GetContainerForItemOverride方法:

public class CustomListBox : ListBox
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new CustomListboxItem();
    }
}

自定义ListBox不再声明ItemTemplate

<controls:CustomListBox ...
    ItemContainerStyle="{StaticResource FilterListBoxItemStyle}" />

您还可以在CustomListboxItem样式中设置NormalBackgroundSelectedBackground属性。

答案 1 :(得分:0)

使用派生类进行分配。按如下方式修改FilterListBoxItemStyle

  1. TargetType更改为ListBoxItem

  2. 制作SelectedBackgroundNormalBackground动态资源 (例如:Background="{DynamicResource NormalBackground}"

  3. 从动画中移除Storyboard.TargetName="ContentContainer"

        ....                                                                                                                                                                                                                              

  4. 然后在每个页面(或您需要的任何范围)上根据需要定义动态资源:

    <ListBox Grid.Row="1" ItemsSource="{Binding CyclesList}" ItemContainerStyle="{StaticResource FilterListBoxItemStyle}" >
        <ListBox.Resources>
            <SolidColorBrush Color="Transparent"
                         x:Key="NormalBackground" />
            <SolidColorBrush Color="Red"
                         x:Key="SelectedBackground" />
        </ListBox.Resources>
    </ListBox>