Home > OS >  ListViewItem Style works from App.xaml while doesn't work from User Control xaml
ListViewItem Style works from App.xaml while doesn't work from User Control xaml

Time:07-01

I wrote my own user control that contains a ListView and its ItemsSource is set runtime. I'd want to set my own ListViewItem style from the user control xaml but I've not been able to get it working, anyway, setting it from App.xaml works flawlessy so I wonder why?

The user control xaml is the following one:

<UserControl x:Class="LogManagerWPF.LogManager"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:LogManagerWPF"
             mc:Ignorable="d" 
             d:DesignHeight="192" d:DesignWidth="400"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <UserControl.Resources>
        <DataTemplate x:Key="DisplayImage">
            <Image Source="{Binding ImageIcon}" Width="16" Height="16"/>
        </DataTemplate>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
        </Style>
    </UserControl.Resources>
    <ListView Margin="0" x:Name="m_lvLog" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" ContextMenuOpening="m_lvLog_ContextMenuOpening" SelectionChanged="m_lvLog_SelectionChanged">
        <ListView.Resources>
            <!-- Windows 7 -->
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />
            <SolidColorBrush x:Key="{x:Static SystemColors.ActiveBorderBrushKey}" Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />
            <!-- Windows 10 -->
            <Style TargetType="{x:Type ListViewItem}">
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background">
                            <Setter.Value>
                                <SolidColorBrush Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"></SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="BorderBrush">
                            <Setter.Value>
                                <SolidColorBrush Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"></SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListView.Resources>
        <ListView.View>
            <GridView x:Name="m_gvLog" AllowsColumnReorder="False">
                <GridViewColumn x:Name="m_icon" Width="28" Header="" CellTemplate="{StaticResource DisplayImage}"/>
                <GridViewColumn x:Name="m_time" Width="Auto" Header="Timestamp" DisplayMemberBinding="{Binding Timestamp}">
                    <GridViewColumn.HeaderContainerStyle>
                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="Foreground" Value="#FF042271" />
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                            <Setter Property="Padding" Value="10,0,0,0" />
                        </Style>
                    </GridViewColumn.HeaderContainerStyle>
                </GridViewColumn>
                <GridViewColumn x:Name="m_messages" Width="100" Header="Message" DisplayMemberBinding="{Binding Message}">
                    <GridViewColumn.HeaderContainerStyle>
                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="Foreground" Value="#FF042271" />
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                            <Setter Property="Padding" Value="10,0,0,0" />
                        </Style>
                    </GridViewColumn.HeaderContainerStyle>
                </GridViewColumn>
            </GridView>
        </ListView.View>
        <ListView.ContextMenu>
            <ContextMenu x:Name="m_contextMenu">
                <MenuItem x:Name="m_menuAutoScroll" Header="Autoscroll" Click="m_menuAutoScroll_Click" IsCheckable="True" />
                <MenuItem x:Name="m_menuClear" Header="Clear Log" Click="m_menuClear_Click"/>
                <MenuItem x:Name="m_menuCopy" Header="Copy to Clipboard" Click="m_menuCopy_Click"/>
                <MenuItem x:Name="m_menuOpenLog" Header="Open Log" Click="m_menuOpenLog_Click"/>
                <MenuItem x:Name="m_menuHorizontalScrollBarVisibility" Header="Set Horizontal ScrollBar Visibility">
                    <MenuItem x:Name="m_menuHorizontalScrollBarEnabled" Header="Enabled" Click="m_menuHorizontalScrollBarEnabled_Click" IsCheckable="True"/>
                    <MenuItem x:Name="m_menuHorizontalScrollBarDisabled" Header="Disabled" Click="m_menuHorizontalScrollBarDisabled_Click" IsCheckable="True"/>
                </MenuItem>
                <MenuItem x:Name="m_menuVerbosity" Header="Set Verbosity">
                    <MenuItem x:Name="m_menuVerbosityLow" Header="Low" Click="m_menuVerbosityLow_Click" IsCheckable="True"/>
                    <MenuItem x:Name="m_menuVerbosityStandard" Header="Standard" Click="m_menuVerbosityStandard_Click" IsCheckable="True"/>
                    <MenuItem x:Name="m_menuVerbosityHigh" Header="High" Click="m_menuVerbosityHigh_Click" IsCheckable="True"/>
                    <MenuItem x:Name="m_menuVerbosityDebug" Header="Debug" Click="m_menuVerbosityDebug_Click" IsCheckable="True"/>
                </MenuItem>
                <MenuItem x:Name="m_menuSeverityFilter" Header="Set Severity Filter">
                    <MenuItem x:Name="m_menuSeverityFilterDebug" Header="Debug" Checked="m_menuSeverityFilterDebug_CheckedChanged" Unchecked="m_menuSeverityFilterDebug_CheckedChanged" IsCheckable="True" StaysOpenOnClick="True"/>
                    <MenuItem x:Name="m_menuSeverityFilterInformation" Header="Information" Checked="m_menuSeverityFilterInformation_CheckedChanged" Unchecked="m_menuSeverityFilterInformation_CheckedChanged" IsCheckable="True" StaysOpenOnClick="True"/>
                    <MenuItem x:Name="m_menuSeverityFilterWarning" Header="Warning" Checked="m_menuSeverityFilterWarning_CheckedChanged" Unchecked="m_menuSeverityFilterWarning_CheckedChanged" IsCheckable="True" StaysOpenOnClick="True"/>
                    <MenuItem x:Name="m_menuSeverityFilterError" Header="Error" Checked="m_menuSeverityFilterError_CheckedChanged" Unchecked="m_menuSeverityFilterError_CheckedChanged" IsCheckable="True" StaysOpenOnClick="True"/>
                    <Separator/>
                    <MenuItem x:Name="m_menuSeverityFilterAll" Header="All" Click="m_menuSeverityFilterAll_Click" StaysOpenOnClick="True"/>
                    <MenuItem x:Name="m_menuSeverityFilterNone" Header="None" Click="m_menuSeverityFilterNone_Click" StaysOpenOnClick="True"/>
                </MenuItem>
                <MenuItem x:Name="m_menuContentFilter" Header="Set Content Filter">
                    <MenuItem x:Name="m_menuContentFilterSet">
                        <MenuItem.Header>
                            <StackPanel Orientation="Horizontal">
                                <Label Content="Set" Padding="0"/>
                                <TextBox x:Name="m_menuContentFilterString" Width="150" Padding="0" Margin="10,0,0,0" VerticalContentAlignment="Center" LostFocus="m_menuContentFilterString_LostFocus"/>
                            </StackPanel>
                        </MenuItem.Header>
                    </MenuItem>
                    <MenuItem x:Name="m_menuContentFilterClear" Header="Clear" Click="m_menuContentFilterClear_Click"/>
                </MenuItem>
            </ContextMenu>
        </ListView.ContextMenu>
    </ListView>
</UserControl>

The styleI'd want to apply works from App.xaml this way:

<Application x:Class="LogManagerWpf_Tester.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
        </Style>
    </Application.Resources>
</Application>

I know the style is not being applied when done from the user control itself because in the output window I see the following errors for each ListViewItem added, that instead doesn't shows when applying the style from the App.xaml:

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 'ListViewItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

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

CodePudding user response:

I didn't like to edit the App.xaml file of an app to put a style that fixes the an user control problem, cause like that I would had to edit every app using such control. Luckily I found a workaround to be placed into the user control contructor that allows me to solve the problem without to edit the applications xaml file:

Style listViewItemStyle = new Style(typeof(ListViewItem));
listViewItemStyle.Setters.Add(new Setter(ListViewItem.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
listViewItemStyle.Setters.Add(new Setter(ListViewItem.VerticalContentAlignmentProperty, VerticalAlignment.Center));

if (!Application.Current.Resources.Contains(typeof(ListViewItem)))
{
    Application.Current.Resources.Add(typeof(ListViewItem), listViewItemStyle);
}

although the above code works I'd like to know why I can't get the desired result directly from the user control xaml.

CodePudding user response:

You need to use BasedOn.

Try this:

<UserControl.Resources>
        <DataTemplate x:Key="DisplayImage">
            <Image Source="{Binding ImageIcon}" Width="16" Height="16"/>
        </DataTemplate>
        <Style x:Key="ListViewStyle" TargetType="{x:Type ListViewItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
        </Style>
    </UserControl.Resources>
    <ListView Margin="0" x:Name="m_lvLog" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" ContextMenuOpening="m_lvLog_ContextMenuOpening" SelectionChanged="m_lvLog_SelectionChanged">
        <ListView.Resources>
            <!-- Windows 7 -->
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />
            <SolidColorBrush x:Key="{x:Static SystemColors.ActiveBorderBrushKey}" Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />
            <!-- Windows 10 -->
            <Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource ListViewItemStyle}">
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background">
                            <Setter.Value>
                                <SolidColorBrush Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"></SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="BorderBrush">
                            <Setter.Value>
                                <SolidColorBrush Color="{Binding SelectedRowBackColor, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"></SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListView.Resources>

Remove the markup in the app.xaml and you should be good to go.

  • Related