C#, WPF - Items of ListView wont show when using ControlTemplate and Binding

0

I'm trying to add Objects of a own-builded class to ListView with GridView in it. The DataBinding is working without any problems and the Items are displayed well and in the correct way. This is the StyleTemplate of the ListView:

<Style x:Key="Orig_FileViewTemplate" TargetType="ListView">            
        <Setter Property="VerticalAlignment" Value="Stretch"></Setter>
        <Setter Property="HorizontalAlignment" Value="Stretch"></Setter>            
    </Style>
<Style x:Key="FileViewTemplate" BasedOn="{StaticResource Orig_FileViewTemplate}" TargetType="ListView">
                    <Setter Property="ItemContainerStyle" Value="{StaticResource FileViewItemContainerTemplate}"></Setter>
                    <EventSetter Event="SelectionChanged" Handler="SelectionChangedOnListView" />                        
                </Style>

And this is one of my ListView-Objects, which use this Style:

<ListView Style="{DynamicResource FileViewTemplate}" Name="lv_FileSourceLV" Grid.Column="1" Grid.Row="0">
                                    <ListView.View>
                                        <GridView >
                                            <GridViewColumn Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,1'}">
                                                <GridViewColumn.CellTemplate>
                                                    <DataTemplate>
                                                        <Image MaxWidth="30" Margin="3,2,3,2" VerticalAlignment="Center" HorizontalAlignment="Center">
                                                            <Image.Style>
                                                                <Style TargetType="{x:Type Image}">
                                                                    <Style.Triggers>
                                                                        <DataTrigger Binding="{Binding IsFolder}" Value="True">
                                                                            <Setter Property="Source" Value="{StaticResource Folder_Icon }" />
                                                                        </DataTrigger>
                                                                        <DataTrigger Binding="{Binding IsFolder}" Value="False">
                                                                            <Setter Property="Source" Value="{StaticResource File_Icon }" />
                                                                        </DataTrigger>
                                                                    </Style.Triggers>
                                                                </Style>
                                                            </Image.Style>
                                                        </Image>
                                                    </DataTemplate>
                                                </GridViewColumn.CellTemplate>
                                            </GridViewColumn>
                                            <GridViewColumn HeaderContainerStyle="{DynamicResource FileViewNameColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,45'}" DisplayMemberBinding="{Binding Name }" />
                                            <GridViewColumn HeaderContainerStyle="{DynamicResource FileViewSizeColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,175'}" DisplayMemberBinding="{Binding Size}" />
                                            <GridViewColumn HeaderContainerStyle="{DynamicResource FileViewDateColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,275'}" DisplayMemberBinding="{Binding Date}" />
                                        </GridView>
                                    </ListView.View>
                                </ListView>

Its working like it should, but now my problem.... I have a huge amount of ListViews of this kind on my GUI and I tried to put the whole style into the ResourceManager to get my code much cleaner and save a lot of redundand code. But when I use the Style like this:

<Style x:Key="FileViewTemplate" BasedOn="{StaticResource Orig_FileViewTemplate}" TargetType="ListView">
                    <Setter Property="ItemContainerStyle" Value="{StaticResource FileViewItemContainerTemplate}"></Setter>
                    <EventSetter Event="SelectionChanged" Handler="SelectionChangedOnListView" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate  TargetType="{x:Type ListView}">
                                <ListView>
                                    <ListView.View>
                                        <GridView>
                                            <GridViewColumn Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,1'}">
                                                <GridViewColumn.CellTemplate>
                                                    <DataTemplate>
                                                        <Image MaxWidth="30" Margin="3,2,3,2" VerticalAlignment="Center" HorizontalAlignment="Center">
                                                            <Image.Style>
                                                                <Style TargetType="{x:Type Image}">
                                                                    <Style.Triggers>
                                                                        <DataTrigger Binding="{Binding IsFolder}" Value="True">
                                                                            <Setter Property="Source" Value="{StaticResource Folder_Icon }" />
                                                                        </DataTrigger>
                                                                        <DataTrigger Binding="{Binding IsFolder}" Value="False">
                                                                            <Setter Property="Source" Value="{StaticResource File_Icon }" />
                                                                        </DataTrigger>
                                                                    </Style.Triggers>
                                                                </Style>
                                                            </Image.Style>
                                                        </Image>
                                                    </DataTemplate>
                                                </GridViewColumn.CellTemplate>
                                            </GridViewColumn>
                                            <GridViewColumn HeaderContainerStyle="{DynamicResource FileViewNameColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,45'}" DisplayMemberBinding="{Binding Name}" />
                                            <GridViewColumn HeaderContainerStyle="{DynamicResource FileViewSizeColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,175'}" DisplayMemberBinding="{Binding Size}" />
                                            <GridViewColumn HeaderContainerStyle="{DynamicResource FileViewDateColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,275'}" DisplayMemberBinding="{Binding Date}" />
                                        </GridView>
                                    </ListView.View>
                                </ListView>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>

And use the ListView in that way:

<ListView Style="{DynamicResource FileViewTemplate}" Name="lv_FileSourceLV" Grid.Column="1" Grid.Row="0"></ListView>

the ListView will be empty on the GUI, even when I add the Items to it. I add them in both ways the same:

lv_FileSourceLV.Items.Add(file)

I think I should handle the DataBinding in a different way, when I use it in a Template, but I dont know how.

Can you tell what I'm doing wrong? Thank you in advance!

Edit: With a GridView resource like

<GridView x:Key="FileViewGrid">

i'm getting this error now:

System.Windows.Markup.XamlParseException HResult=0x80131501
Message='Set property 'System.Windows.FrameworkElement.Style' threw an exception.' Line number '331' and line position '106'. Inner Exception 1: InvalidOperationException: View can't be shared by more than one ListView.

This is my current code:

<DataTemplate x:Key="FileViewNameTemplate">
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
    <DataTemplate x:Key="FileViewSizeTemplate">
        <TextBlock Text="{Binding Size}"/>
    </DataTemplate>
    <DataTemplate x:Key="FileViewDateTemplate">
        <TextBlock Text="{Binding Date}"/>
    </DataTemplate>
    <DataTemplate x:Key="FileViewImageTemplate">
        <Image MaxWidth="30" Margin="3,2,3,2" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Image.Style>
                <Style TargetType="{x:Type Image}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsFolder}" Value="True">
                            <Setter Property="Source" Value="{StaticResource Folder_Icon }" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding IsFolder}" Value="False">
                            <Setter Property="Source" Value="{StaticResource File_Icon }" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>
    </DataTemplate>
    <GridView x:Key="FileViewGrid" x:Shared="False">
            <GridViewColumn CellTemplate="{StaticResource FileViewImageTemplate}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,1'}" />
            <GridViewColumn CellTemplate="{StaticResource FileViewNameTemplate}" HeaderContainerStyle="{DynamicResource FileViewNameColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,45'}"/>
            <GridViewColumn CellTemplate="{StaticResource FileViewSizeTemplate}" HeaderContainerStyle="{DynamicResource FileViewSizeColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,175'}"/>
            <GridViewColumn CellTemplate="{StaticResource FileViewDateTemplate}" HeaderContainerStyle="{DynamicResource FileViewDateColumn}" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListView}, Converter={StaticResource percentageConverter}, ConverterParameter='0,275'}"/>
    </GridView>
    <Style x:Key="FileViewTemplate" BasedOn="{StaticResource Orig_FileViewTemplate}" TargetType="ListView">
        <Setter Property="ItemContainerStyle" Value="{StaticResource FileViewItemContainerTemplate}"></Setter>
        <EventSetter Event="SelectionChanged" Handler="SelectionChangedOnListView" />
        <Setter Property="View" Value="{DynamicResource FileViewGrid}"/>
    </Style>
    

I also tried to put the "x:Shared=False" Property to GridView and Style and put the GridView directly into the View-Property of "FileViewDateTemplate. Anything without success.

c#
wpf
listview
templates
binding
asked on Stack Overflow Sep 3, 2020 by TiK • edited Sep 3, 2020 by TiK

1 Answer

0

It's wrong to have a ListView in the ControlTemplate of a ListView. You should not be setting the Template property at all.

Add a setter for the View property instead, which uses a shared GridView resource - and optionally also make the DataTemplate a resource.

You would usually also not programmatically add elements to the Items collection of an ItemsControl. There should instead be an ObservableCollection property in a main view model to which the ItemsSource property would be bound.

<Window.Resources>
    <DataTemplate x:Key="MyCellTemplate">
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
    <GridView x:Key="MyGridView" x:Shared="False">
        <GridViewColumn Header="Name"
                        CellTemplate="{StaticResource MyCellTemplate}"/>
    </GridView>
    <Style x:Key="MyListViewStyle" TargetType="ListView">
        <Setter Property="View" Value="{StaticResource MyGridView}"/>
    </Style>
</Window.Resources>
<Grid>
    <ListView Style="{StaticResource MyListViewStyle}"
              ItemsSource="{Binding MyItems}"/>
</Grid>

Edit: A shared Style resource should also work:

<Style x:Key="MyListViewStyle" x:Shared="False" TargetType="ListView">
    <Setter Property="View">
        <Setter.Value>
            <GridView>
                <GridViewColumn Header="Name"
                    CellTemplate="{StaticResource MyCellTemplate}"/>
            </GridView>
        </Setter.Value>
    </Setter>
</Style>
answered on Stack Overflow Sep 3, 2020 by Clemens • edited Sep 3, 2020 by Clemens

User contributions licensed under CC BY-SA 3.0