ListBox与Grid作为ItemsPanelTemplate产生奇怪的绑定错误 [英] ListBox with Grid as ItemsPanelTemplate produces weird binding errors

查看:168
本文介绍了ListBox与Grid作为ItemsPanelTemplate产生奇怪的绑定错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ListBox控件,我在网格布局中提供了固定数量的ListBoxItem对象。所以我把我的ItemsPanelTemplate设置为一个网格。



我正在从后面的代码访问Grid,以配置RowDefinitions和ColumnDefinitions。



到目前为止,这一切都按照我的期望工作。我有一些自定义的IValueConverter实现,用于返回每个ListBoxItem应该出现的Grid.Row和Grid.Column。



但是我有时会收到奇怪的绑定错误,而且不能确切地知道他们在发生什么,或者即使他们在我的代码中。



这是我得到的错误:


System.Windows.Data错误:4:找不到与引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls绑定的源代码。 ItemsControl',AncestorLevel ='1''。 BindingExpression:Path = Horizo​​ntalContentAlignment; DataItem = null; target元素是'ListBoxItem'(Name ='');目标属性是Horizo​​ntalContentAlignment(类型'Horizo​​ntalAlignment')


任何人都可以解释发生了什么? / p>

哦,这是我的XAML:

 < UserControl。资源> 
<! - 值转换器 - >
< v:GridRowConverter x:Key =GridRowConverter/>
< v:GridColumnConverter x:Key =GridColumnConverter/>
< v:DevicePositionConverter x:Key =DevicePositionConverter/>
< v:DeviceBackgroundConverter x:Key =DeviceBackgroundConverter/>

< Style x:Key =DeviceContainerStyleTargetType ={x:Type ListBoxItem}>
< Setter Property =FocusVisualStyleValue ={x:Null}/>
< Setter Property =BackgroundValue =Transparent/>

< Setter Property =Grid.RowValue ={Binding Path = DeviceId,Converter = {StaticResource GridRowConverter}}/>
< Setter Property =Grid.ColumnValue ={Binding Path = DeviceId,Converter = {StaticResource GridColumnConverter}}/>

< Setter属性=模板>
< Setter.Value>
< ControlTemplate TargetType ={x:Type ListBoxItem}>
< Border CornerRadius =2BorderThickness =1BorderBrush =WhiteMargin =2Name =Bd
Background ={Binding Converter = {StaticResource DeviceBackgroundConverter}}> ;
< TextBlock FontSize =12Horizo​​ntalAlignment =CenterVerticalAlignment =Center
Text ={Binding Path = DeviceId,Converter = {StaticResource DevicePositionConverter}}>
< TextBlock.LayoutTransform>
< RotateTransform Angle =270/>
< /TextBlock.LayoutTransform>
< / TextBlock>
< / Border>
< ControlTemplate.Triggers>
< Trigger Property =IsSelectedValue =true>
< Setter TargetName =BdProperty =BorderThicknessValue =2/>
< Setter TargetName =BdProperty =MarginValue =1/>
< / Trigger>
< /ControlTemplate.Triggers>
< / ControlTemplate>
< /Setter.Value>
< / Setter>
< / Style>
< /UserControl.Resources>

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

< StackPanel Grid.Row =0Orientation =Horizo​​ntal>
< Image Margin =20,3,3,3Source =Barcode.GIFWidth =60Stretch =Fill/>
< / StackPanel>

< ListBox ItemsSource ={Binding}x:Name =lstDevicesGrid.Row =1
ItemContainerStyle ={StaticResource DeviceContainerStyle}
背景= #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>

解决方案

绑定问题来自ListBoxItem的默认样式。默认情况下,将样式应用于元素WPF会查找默认样式,并将自定义样式中未专门设置的每个属性与默认样式应用。请参阅这个伟大的博文由Ian Griffiths更多有关此行为的详细信息。



回到我们的问题。这是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.Horizo​​ntalContentAlignment>
< Setter.Value>
< Binding Path =Horizo​​ntalContentAlignmentRelativeSource ={RelativeSource Mode = FindAncestor,AncestorType = ItemsControl,AncestorLevel = 1}/>
< /Setter.Value>
< / Setter>
< Setter Property =Control.VerticalContentAlignment>
< Setter.Value>
< Binding Path =VerticalContentAlignmentRelativeSource ={RelativeSource Mode = FindAncestor,AncestorType = ItemsControl,AncestorLevel = 1}/>
< /Setter.Value>
< / Setter>
< Setter Property =Control.Padding>
< Setter.Value>
<厚度>
2,0,0,0
< / Thickness>
< /Setter.Value>
< / Setter>
< Setter Property =Control.Template>
< Setter.Value>
< ControlTemplate TargetType ={x:Type ListBoxItem}>
...
< / ControlTemplate>
< /Setter.Value>
< / Setter>
< / Style>

请注意,我已经删除了ControlTemplate以使其紧凑(我已经使用 StyleSnooper 来检索样式)。您可以看到有一个绑定与相对源设置为祖先类型为ItemsControl。所以在你的情况下,绑定时创建的ListBoxItems没有找到它们的ItemsControl。您可以提供更多关于ListBox的ItemsSource的信息吗?



PS:删除错误的一种方法是在自定义样式中为Horizo​​ntalContentAlignment和VerticalContentAlignment创建新的设置器。


I've got a ListBox control and I'm presenting a fixed number of ListBoxItem objects in a grid layout. So I've set my ItemsPanelTemplate to be a Grid.

I'm accessing the Grid from code behind to configure the RowDefinitions and ColumnDefinitions.

So far it's all working as I expect. I've got some custom IValueConverter implementations for returning the Grid.Row and Grid.Column that each ListBoxItem should appear in.

However I get weird binding errors sometimes, and I can't figure out exactly why they're happening, or even if they're in my code.

Here's the error I get:

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')

Can anybody explain what's going on?

Oh, and, here's my 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>

解决方案

The binding problem comes from the default style for ListBoxItem. By default when applying styles to elements WPF looks for the default styles and applies each property that is not specifically set in the custom style from the default style. Refer to this great blog post By Ian Griffiths for more details on this behavior.

Back to our problem. Here is the default style for 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>

Note that I have removed the ControlTemplate to make it compact (I have used StyleSnooper to retrieve the style). You can see that there is a binding with a relative source set to ancestor with type ItemsControl. So in your case the ListBoxItems that are created when binding did not find their ItemsControl. Can you provide more info with what is the ItemsSource for your ListBox?

P.S.: One way to remove the errors is to create new setters for HorizontalContentAlignment and VerticalContentAlignment in your custom Style.

这篇关于ListBox与Grid作为ItemsPanelTemplate产生奇怪的绑定错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆