列表框与电网作为ItemsPanelTemplate产生奇怪的绑定错误(ListBox with G

2019-08-31 07:51发布

我有一个列表框控件,我提出在网格布局中一个ListBoxItem对象的固定数目。 所以,我把我的ItemsPanelTemplate是一个网格。

我从代码访问网格的背后配置RowDefinitions和ColumnDefinitions。

到目前为止,我希望一切正常。 我有一些自定义的IValueConverter实现返回的Grid.Row和Grid.Column每一个ListBoxItem应该出现英寸

不过我得到奇怪的绑定错误,有时,我无法弄清楚到底他们为什么发生,或者即使他们是在我的代码。

这是我得到的错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'ListBoxItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

任何人能解释这是怎么回事?

哦,还有,这里是我的XAML:

<UserControl.Resources>
    <!-- Value Converters -->
    <v:GridRowConverter x:Key="GridRowConverter" />
    <v:GridColumnConverter x:Key="GridColumnConverter" />
    <v:DevicePositionConverter x:Key="DevicePositionConverter" />
    <v:DeviceBackgroundConverter x:Key="DeviceBackgroundConverter" />

    <Style x:Key="DeviceContainerStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="Background" Value="Transparent" />

        <Setter Property="Grid.Row" Value="{Binding Path=DeviceId, Converter={StaticResource GridRowConverter}}" />
        <Setter Property="Grid.Column" Value="{Binding Path=DeviceId, Converter={StaticResource GridColumnConverter}}" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border CornerRadius="2" BorderThickness="1" BorderBrush="White" Margin="2" Name="Bd"
                            Background="{Binding Converter={StaticResource DeviceBackgroundConverter}}">
                        <TextBlock FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" 
                                Text="{Binding Path=DeviceId, Converter={StaticResource DevicePositionConverter}}" >
                            <TextBlock.LayoutTransform>
                                <RotateTransform Angle="270" />
                            </TextBlock.LayoutTransform>
                        </TextBlock>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter TargetName="Bd" Property="BorderThickness" Value="2" />
                            <Setter TargetName="Bd" Property="Margin" Value="1" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>            
    </Style>        
</UserControl.Resources>

<Border CornerRadius="3" BorderThickness="3" Background="#FF333333" BorderBrush="#FF333333" >
    <Grid ShowGridLines="False">
        <Grid.RowDefinitions>
            <RowDefinition Height="15" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <Image Margin="20,3,3,3" Source="Barcode.GIF" Width="60" Stretch="Fill" />
        </StackPanel>

        <ListBox ItemsSource="{Binding}" x:Name="lstDevices" Grid.Row="1" 
                 ItemContainerStyle="{StaticResource DeviceContainerStyle}"
                 Background="#FF333333"
                 SelectedItem="{Binding SelectedDeviceResult, ElementName=root, Mode=TwoWay}" >
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.LayoutTransform>
                            <RotateTransform Angle="90" />
                        </Grid.LayoutTransform>                            
                    </Grid>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
    </Grid>
</Border>

Answer 1:

结合问题来自于对ListBoxItem的默认样式。 默认情况下,将样式应用于元素时,WPF查找默认的样式,并应用没有特别从默认风格自定义样式设置每个属性。 请参考这个伟大的博客文章由伊恩·格里菲思有关此行为的更多细节。

回到我们的问题。 下面是ListBoxItem的默认样式:

<Style
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    TargetType="{x:Type ListBoxItem}">
    <Style.Resources>
       <ResourceDictionary/>
    </Style.Resources>
    <Setter Property="Panel.Background">
       <Setter.Value>
          <SolidColorBrush>
        #00FFFFFF
          </SolidColorBrush>
       </Setter.Value>
    </Setter>
    <Setter Property="Control.HorizontalContentAlignment">
       <Setter.Value>
          <Binding Path="HorizontalContentAlignment" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl, AncestorLevel=1}"/>
       </Setter.Value>
    </Setter>
    <Setter Property="Control.VerticalContentAlignment">
       <Setter.Value>
          <Binding Path="VerticalContentAlignment" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl, AncestorLevel=1}"/>
       </Setter.Value>
    </Setter>
    <Setter Property="Control.Padding">
       <Setter.Value>
          <Thickness>
        2,0,0,0
          </Thickness>
       </Setter.Value>
    </Setter>
    <Setter Property="Control.Template">
       <Setter.Value>
          <ControlTemplate TargetType="{x:Type ListBoxItem}">
             ...
          </ControlTemplate>
       </Setter.Value>
    </Setter>
 </Style>

请注意,我已经删除了控件模板,使其小巧(我用StyleSnooper -要检索的样式)。 你可以看到,有一个与设置为祖先类型的ItemsControl相对来源的绑定。 所以你的情况是有约束力没有找到他们的ItemsControl时创建的ListBoxItems。 你能提供什么是你的ListBox中的ItemsSource更多信息?

PS:删除错误的一种方法是在您的自定义样式来创建Horizo​​ntalContentAlignment和VerticalContentAlignment新制定者。



Answer 2:

设置OverridesDefaultStyleTrue在你ItemContainerStyle也将解决这些问题。

<Style TargetType="ListBoxItem">
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <!-- set the rest of your setters, including Template, here -->
</Style>


Answer 3:

这是一个常见的问题有ListBoxItem S和其他短暂*Item的容器。 他们是异步创建/上的苍蝇,而ItemsControl加载/渲染。 你必须重视ListBox.ItemContainerGeneratorStatusChanged事件和等待状态成为ItemsGenerated试图访问它们。



Answer 4:

这是这里的其他答案的汞齐,但对我来说,我不得不套用Setter在两个地方解决错误,虽然这个使用自定义时是VirtualizingWrapPanel

如果我删除下面的任何一个Setter声明,我的错误再次出现。

        <ListView>
            <ListView.Resources>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Left" />
                    <Setter Property="VerticalContentAlignment" Value="Top" />
                </Style>
            </ListView.Resources>
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Left" />
                    <Setter Property="VerticalContentAlignment" Value="Top" />
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <controls:VirtualizingWrapPanel />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
        </ListView>

我真的没有在此刻进一步调查的时间,但我怀疑这是与该JTango提到在他的回答中默认的风格 - 我真的不定制我的模板,以一个巨大的程度。

我认为有更多的里程将出过其他的答案,但我想我会发布此上关的机会,它可以帮助别人在同一条船上。

大卫施密特的回答看起来似乎描述的根本原因。



Answer 5:

我有同样的问题,因为你,我只是想分享什么是我的解决方案。 我已经尝试了所有选项,从这个职位,但最后一个是最适合我 - THX克里斯。

所以,我的代码:

<ListBox.Resources>
    <Style x:Key="listBoxItemStyle" TargetType="ListBoxItem">
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="MinWidth" Value="24"/>
        <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
    </Style>

    <Style TargetType="ListBoxItem" BasedOn="{StaticResource listBoxItemStyle}"/>
</ListBox.Resources>

<ListBox.ItemContainerStyle>
    <Binding Source="{StaticResource listBoxItemStyle}"/>
</ListBox.ItemContainerStyle>

<ListBox.ItemsPanel>
    <ItemsPanelTemplate>
        <WrapPanel Orientation="Horizontal" IsItemsHost="True" MaxWidth="170"/>
    </ItemsPanelTemplate>
</ListBox.ItemsPanel>

我还发现,如果自定义这个错误不会出现ItemsPanelTemplate不存在。



Answer 6:

我刚刚遇到了同样类型的错误:

System.Windows.Data错误:4:不能用于与参考 '的RelativeSource FindAncestor,AncestorType =' 结合找到源System.Windows.Controls.ItemsControl 'AncestorLevel = '1''。 BindingExpression:路径= Horizo​​ntalContentAlignment; 的DataItem = NULL; 目标元素是 'ListBoxItem的'(名称= ''); 目标属性是“Horizo​​ntalContentAlignment”(类型“的Horizo​​ntalAlignment”)

发生这种情况而做这样的绑定:

<ListBox ItemsSource="{Binding Path=MyListProperty}"  />

我的数据上下文对象的这个属性:

public IList<ListBoxItem> MyListProperty{ get; set;}

一些尝试后,我发现该错误只触发时的项目数超过了我的ListBox的可见高度(例如,当垂直滚动条出现)。 于是我立即想到了虚拟化,并试图这样的:

<ListBox ItemsSource="{Binding Path=MyListProperty}" VirtualizingStackPanel.IsVirtualizing="False" />

这解决了这个问题对我来说。 虽然我宁愿保持虚拟化开启我没有使用任何更多的时间去钻研它。 我的应用程序是在复杂的一面与电网mulitiple水平,码头围板等和一些非同步的方法调用了一下。 我没能重现一个简单的应用问题。



Answer 7:

另一种解决方法/解决方案,为我工作是为了抑制这些错误(实际上,它似乎更适合叫他们警告),通过设置数据绑定源开关级类或顶层窗口的构造函数中的关键 -

#if DEBUG     
    System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level =
        System.Diagnostics.SourceLevels.Critical;
#endif

参考: 如何抑制System.Windows.Data错误警告信息



Answer 8:

根据该数据模板化概述 MSDN上, DataTemplates应该被用作ItemTemplate定义数据的显示方式,而Style将被用作ItemContainerStyle样式刚刚产生的容器,如ListBoxItem

然而,似乎您试图使用后者做了前者的工作。 我无法重新创建你的情况没有太多的代码,但我怀疑的是,在集装箱式的数据绑定做可能是在假设视觉/逻辑树扔扳手。

我也不禁想到,基于项目的信息项的自定义布局要求创建自定义Panel 。 这可能是自定义更好的Panel布局的项目比对项目给自己制定出与一个鲁贝戈德堡品种IValueConverters



Answer 9:

如果你想完全取代ListBoxItem的模板,使得没有选择可见的(也许你想要的外观ItemsControl用的分组/等行为ListBox ),那么你可以使用这个风格:

<Style TargetType="ListBoxItem">
  <Setter Property="Margin" Value="2" />
  <Setter Property="FocusVisualStyle" Value="{x:Null}" />
  <Setter Property="OverridesDefaultStyle" Value="True" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ListBoxItem}">
        <ContentPresenter Content="{TemplateBinding ContentControl.Content}" 
                          HorizontalAlignment="Stretch" 
                          VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" 
                          SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

这个模板还排除了标准Border包装。 如果你需要,你可以用这个代替模板:

<Border BorderThickness="{TemplateBinding Border.BorderThickness}" 
        Padding="{TemplateBinding Control.Padding}" 
        BorderBrush="{TemplateBinding Border.BorderBrush}" 
        Background="{TemplateBinding Panel.Background}" 
        SnapsToDevicePixels="True">
  <ContentPresenter Content="{TemplateBinding ContentControl.Content}" 
                    ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" 
                    HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" 
                    VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" 
                    SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>

如果你并不需要所有这些TemplateBinding值,那么你可以删除一些性能。



Answer 10:

这为我工作。 在Application.xaml文件中把这个。

<Application.Resources>
    <Style TargetType="ListBoxItem">
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
    </Style>
</Application.Resources>

从...

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/42cd1554-de7a



Answer 11:

简单地创建类型为“ComboBoxItem”不起作用默认样式,因为它通过组合框的默认“ItemContainerStyle”覆盖。 要真正摆脱这一点,你需要更改组合框的默认“ItemContainerStyle”,就像这样:

<Style TargetType="ComboBox">
    <Setter Property="ItemContainerStyle">
        <Setter.Value>                
            <Style TargetType="ComboBoxItem">
                <Setter Property="HorizontalContentAlignment" Value="Left" />
                <Setter Property="VerticalContentAlignment" Value="Center" />
            </Style>
        </Setter.Value>
    </Setter>
</Style>


Answer 12:

我开始运行到这个问题,即使我的列表框既具有风格和ItemContainerStyle集 - 而这些命名样式已经确定Horizo​​ntalContentAlignment。 我使用CheckBox控件来开启/关闭实时过滤在我的列表框,这似乎是导致项目而不是拉从默认的样式,而不是我分配的样式。 大多数错误会发生在第一时间实时过滤踢,但此后将继续扔在每一个变化2个错误。 我觉得有趣的是在我的收藏正好2个纪录是空的,所以没有什么在项目中显示。 因此,这似乎已经contibuted。 我打算创建默认的数据显示,当一个记录是空的。

卡特的建议为我工作。 添加无键和定义的Horizo​​ntalContentAlignment物业解决问题的TargetType =“ListBoxItem的”独立的“默认”的风格。 我甚至没有需要设置OverridesDefaultStyle属性吧。



文章来源: ListBox with Grid as ItemsPanelTemplate produces weird binding errors