[.net] ListBox mit Grid als ItemsPanelTemplate erzeugt seltsame Bindungsfehler


Answers

Wenn Sie in Ihrem ItemContainerStyle OverridesDefaultStyle auf True ItemContainerStyle werden diese Probleme ebenfalls ItemContainerStyle .

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

Ich habe ein ListBox-Steuerelement und ich präsentiere eine feste Anzahl von ListBoxItem-Objekten in einem Rasterlayout. Also habe ich meine ItemsPanelTemplate als Grid festgelegt.

Ich greife auf das Grid von Code zurück, um die RowDefinitions und ColumnDefinitions zu konfigurieren.

Bis jetzt funktioniert alles wie erwartet. Ich habe einige benutzerdefinierte IValueConverter-Implementierungen für die Rückgabe der Grid.Row und Grid.Column, die jedes ListBoxItem angezeigt werden sollte.

Allerdings bekomme ich manchmal seltsame Bindungsfehler, und ich kann nicht genau herausfinden, warum sie passieren, oder sogar, wenn sie in meinem Code sind.

Hier ist der Fehler, den ich bekomme:

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

Kann mir jemand erklären, was vor sich geht?

Oh, und hier ist mein 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>




Dies ist ein Amalgam der anderen Antworten hier, aber für mich musste ich den Setter an zwei Stellen anwenden, um den Fehler zu beheben, obwohl dies mit einem benutzerdefinierten VirtualizingWrapPanel

Wenn ich eine der folgenden Setter Deklarationen Setter , werden meine Fehler erneut angezeigt.

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

Ich habe im Moment nicht die Zeit, weiter zu recherchieren, aber ich vermute, dass es mit dem Standard-Stil zusammenhängt, den JTango in seiner Antwort erwähnt - ich passe meine Vorlage nicht wirklich in hohem Maße an.

Ich denke, es gibt mehr Kilometer, die man von den anderen Antworten haben könnte, aber ich dachte, ich würde dies posten, wenn es jemandem im selben Boot hilft.

David Schmitts Antwort sieht so aus, als könnte sie die Ursache beschreiben.




Das hat für mich funktioniert. Fügen Sie das in Ihrer Application.xaml-Datei ein.

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

von...

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




Ich habe gerade die gleiche Art von Fehler festgestellt:

System.Windows.Data Fehler: 4: Die Quelle für die Bindung mit der Referenz 'RelativeSource FindAncestor, AncestorType =' System.Windows.Controls.ItemsControl ', AncestorLevel =' 1 '' kann nicht gefunden werden. BindingExpression: Pfad = HorizontalContentAlignment; Datenelement = null; Zielelement ist 'ListBoxItem' (Name = ''); Zieleigenschaft ist 'HorizontalContentAlignment' (Typ 'HorizontalAlignment')

Dies geschah während einer Bindung wie folgt:

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

Zu dieser Eigenschaft in meinem Datenkontextobjekt:

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

Nach einigen Experimenten entdeckte ich, dass der Fehler nur ausgelöst wurde, wenn die Anzahl der Elemente die sichtbare Höhe meiner ListBox überschritt (z. B. wenn vertikale Bildlaufleisten angezeigt werden). Also habe ich sofort über Virtualisierung nachgedacht und folgendes versucht:

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

Das hat das Problem für mich gelöst. Obwohl ich es vorziehen würde, die Virtualisierung eingeschaltet zu lassen, brauchte ich nicht mehr Zeit, um darin einzutauchen. Meine Anwendung ist ein bisschen auf der komplexen Seite mit mehreren Ebenen von Grids, Dock-Panels usw. und einigen asynch Methodenaufrufen. Ich konnte das Problem nicht in einer einfacheren Anwendung reproduzieren.




Gemäß der Data Templating-Übersicht in MSDN sollten DataTemplates als ItemTemplate , um zu definieren, wie die Daten dargestellt werden, während ein Style als ItemContainerStyle , um nur den generierten Container wie ListBoxItem .

Es scheint jedoch, dass Sie versuchen, das Letztere zu benutzen, um die Arbeit des ersteren zu erledigen. Ich kann Ihre Situation nicht ohne viel mehr Code neu erstellen, aber ich vermute, dass die Datenbindung im Containerstil einen Haken in den angenommenen visuellen / logischen Baum werfen könnte.

Ich kann auch nicht anders, als zu denken, dass ein benutzerdefiniertes Layout von Elementen, das auf den Informationen des Elements basiert, das Erstellen eines benutzerdefinierten Panel . Es ist wahrscheinlich besser für das benutzerdefinierte Panel , die Elemente zu gestalten, als für die Elemente, die sich mit einem Rube Goldberg Sortiment von IValueConverters .




Ich fing an, in dieses Problem zu laufen, obwohl meine ListBox sowohl einen Stil als auch einen ItemContainerStyle hatte - und diese benannten Stile hatten bereits HorizontalContentAlignment definiert. Ich habe CheckBox-Steuerelemente verwendet, um die Live-Filterung auf meiner ListBox ein- und auszuschalten, und dies schien zu bewirken, dass die Elemente statt vom zugewiesenen Stil aus dem Standardstil gezogen wurden. Die meisten Fehler treten auf, wenn die Live-Filterung zum ersten Mal gestartet wird, danach werden jedoch bei jeder Änderung 2 Fehler ausgegeben. Ich finde es interessant, dass genau 2 Datensätze in meiner Sammlung leer waren und somit nichts im Objekt angezeigt werden konnte. Das scheint also beigetragen zu haben. Ich plane, Standarddaten zu erstellen, die angezeigt werden, wenn ein Datensatz leer ist.

Carters Vorschlag funktionierte für mich. Das Hinzufügen eines separaten "Standard" -Stils ohne Schlüssel und eines TargetType = "ListBoxItem", mit dem die Eigenschaft HorizontalContentAlignment definiert wurde, hat das Problem gelöst. Ich musste nicht einmal die OverridesDefaultStyle-Eigenschaft dafür festlegen.






Links