Laden...

ListView zeigt nur Objektnamen an, Problem mit ContentPresenter und DataTemplates

Letzter Beitrag vor einem Jahr 14 Posts 877 Views
ListView zeigt nur Objektnamen an, Problem mit ContentPresenter und DataTemplates

Hey zusammen,

in meinem Projekt habe ich einen Style angelegt für alle ListBoxItems (Damit alle die selben Farben haben und die selben Triggers,etc.). Nun möchte ich gern eine neue ListView anlegen als GridView und mit DataTemplates (Mein Problem ist auch bei DisplayMemberBinding vorhanden). Leider werden mir meine Einträge nicht im ListView angezeigt, sondern nur der Objektname. Dies liegt an dem ContentPresenter im Style. Gelöst wäre es eigentlich wenn ich den ersetze durch einen GridViewRowPresenter, allerdings funktioniert dann der Style nicht mehr an den anderen ListViews. Wie kann ich das Problem am besten lösen? Danke schon nmal für eure Hilfe und hier noch der relevante Code dazu:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="Item.Static.Border" Color="Transparent"/>
    <SolidColorBrush x:Key="Item.MouseOver.Background" Color="{Binding Source={StaticResource darkgray}, Path=Color}"/>
    <SolidColorBrush x:Key="Item.MouseOver.Border" Color="{Binding Source={StaticResource yellow}, Path=Color}"/>
    <SolidColorBrush x:Key="Item.SelectedActive.Background" Color="{Binding Source={StaticResource gray}, Path=Color}"/>
    <SolidColorBrush x:Key="Item.SelectedActive.Border" Color="{Binding Source={StaticResource yellow}, Path=Color}"/>
    <SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="{Binding Source={StaticResource gray}, Path=Color}"/>
    <SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="{Binding Source={StaticResource white}, Path=Color}"/>

    <Style TargetType="ListViewItem">
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="BorderBrush" Value="{StaticResource Item.Static.Border}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
                            <Setter Property="BorderThickness" TargetName="Bd" Value="1"/>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                <Condition Property="IsSelected" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
                            <Setter Property="BorderThickness" TargetName="Bd" Value="1"/>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                <Condition Property="IsSelected" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
                            <Setter Property="BorderThickness" TargetName="Bd" Value="1"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
 <ListView Grid.Row="1" Grid.ColumnSpan="2" Height="200" Background="Transparent" Margin="0 10 0 0" FontSize="20" VerticalAlignment="Top" ItemsSource="{Binding ActionList}">
     <ListView.View>
         <GridView>
             <GridViewColumn Header="Test" DisplayMemberBinding="{Binding Name}"/>
             <GridViewColumn Header="Eintrag" Width="80">
                 <GridViewColumn.CellTemplate>
                     <DataTemplate>
                         <TextBlock Text="{Binding Entry}"/>
                     </DataTemplate>
                 </GridViewColumn.CellTemplate>
             </GridViewColumn>
             <GridViewColumn Header="Bezeichnung" Width="150">
                 <GridViewColumn.CellTemplate>
                     <DataTemplate>
                         <TextBlock Text="{Binding Name}"/>
                     </DataTemplate>
                 </GridViewColumn.CellTemplate>
             </GridViewColumn>
             <GridViewColumn Header="Schadenscode" Width="150">
                 <GridViewColumn.CellTemplate>
                     <DataTemplate>
                         <TextBlock Text="{Binding FailureCode}"/>
                     </DataTemplate>
                 </GridViewColumn.CellTemplate>
             </GridViewColumn>
             <GridViewColumn Header="Aktionscode" Width="150">
                 <GridViewColumn.CellTemplate>
                     <DataTemplate>
                         <TextBlock Text="{Binding ActionCode}"/>
                     </DataTemplate>
                 </GridViewColumn.CellTemplate>
             </GridViewColumn>
         </GridView>
     </ListView.View>
 </ListView>

Sollte bei deinem ControlTemplate nicht ListViewItem (statt ListBoxItem) stehen?

<ControlTemplate TargetType="{x:Type ListViewItem}">

Das stimmt, da hat sich noch ein kleiner Fehler eingeschlichen, danke! Aber das ändert leider nichts an meinem Problem.

Evtl. mußt du noch Content und ContentTemplate bei dem ContentPresenter übernehmen (d.h. daran binden), s.a. die Antwort in Wpf – ListViewItem custom template: ContentPresenter stays empty.

Ansonsten hilft evtl. WPF ItemsControl – Advanced.

Evtl. mußt du noch Content und ContentTemplate bei dem ContentPresenter übernehmen (d.h. daran binden), s.a. die Antwort in Wpf – ListViewItem custom template: ContentPresenter stays empty.

Das hab ich auch schon versucht. hat leider auch nichts gebracht.

Ansonsten hilft evtl. WPF ItemsControl – Advanced.

Weiß nicht genau, was hier für mich zutrifft 😦

Funktioniert es denn, wenn du den gesamten Style testweise direkt als ListView.ItemContainerStyle benutzt? Oder aber mal den XAML-Code aus dem ersten Link übernimmst und dann dort das Binding einbaust?

Den 2. Link habe ich dir nur gegeben, weil dort eben auch UI-Anpassungen an einem ItemsControl erklärt werden (eine ListView ist ja nur ein spezielles ItemsControl).

Wie mach ich das am besten? Mein Style ist ja in einem RessourceDictionary. Dort kann ich <ListView.ItemContainerStyle>nicht setzen, da er nciht weiß auf welches ListView er zugreifen soll.

Ich meine ja nur zum Austesten, also direkt in das ListView reinkopieren:

 <ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
      <!-- ... -->
    </Style>
 </ListView.ItemContainerStyle>

Tausche den ContentPresenter gegen einen GridViewRowPresenter!

<!--<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
					  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
					  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />-->
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
					  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
					  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />

Tausche den ContentPresenter gegen einen GridViewRowPresenter!

Das hab ich oben bereits ausgeschlossen, da sich der Style dann nicht mehr auf die normalen ListViews einsetzen lässt und dort dann Probleme macht.

Ich meine ja nur zum Austesten, also direkt in das ListView reinkopieren:

<ListView.ItemContainerStyle>
   <Style TargetType="ListViewItem">
     <!-- ... -->
   </Style>
</ListView.ItemContainerStyle>

Das klappt. Aber wie bringe ich das am besten in meinem Style unter? Ich nehme an das klappt, weil damit mein erstellter Default Style dadurch nicht mehr genutzt wird. Sobald ich nämlich BasedOn="{StaticResource {x:Type ListViewItem}}" noch in deinen Code einfüge, geht es wieder nicht.

Gib deinem Style (in den Resources) mal einen Namen, d.h.

<Style x:Key="MyDefaultListViewItem" TargetType="ListViewItem">

und verwende den dann

ItemContainerStyle="{StaticResource lvItemHover}"
<!-- bzw. --/>
BasedOn="{StaticResource MyDefaultListViewItem}"

(falls du noch spezifische Änderungen an dem konkreten ListView-Style machen möchtest)

Falls das auch nicht funktioniert:

Was passiert, wenn du den <ContentPresenter ... /> mal komplett aus deinem Style entfernst?

Edit:

Du mußt wohl wirklich einen GridViewRowPresenter benutzen, s. Beitrag in Basic style definition (ist zwar aus dem NoesisGUI-Forum, aber dieses beruht auf WPF).

Danke euch.

Ich hab jetzt zwei identische Styles angelegt. Der eine mit x:Key="GridViewRow"welcher dann den GridViewRowPresenterenthält. Und der Default-Style enthält dann den ContentPresenter

Schade, aber immerhion gibt es einen Workaround 😄

Ist nur etwas blöd, das ich jetzt an zwei Stellen den Style ändern muss 😦

Du könntest das ControlTemplate als eigene Resource anlegen (ohne Border + ContentPresenter/GridViewRowPresenter) und dann in den jeweiligen Styles dieses per BasedOn einfügen und dann jeweils nur den geänderten Teil individuell einfügen - so hättest du zumindestens für die Trigger nur einmalig den XAML-Code.

Edit: Oder eben nur den Trigger auslagern (je nachdem, ob du evtl. noch andere Eigenschaften außer Border ändern möchtest).

Hab das ControlTemplate separiert, danke 😃