ListView Row background 색상변경 질문드립니다.

<Window.Resources>
    <Style TargetType="{x:Type ListViewItem}">
        <Style.Triggers>
            <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                <Setter Property="Background" Value="#1e1e1e"></Setter>
                <Setter Property="Foreground" Value="#ffffff"></Setter>
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Margin" Value="0"/>
            </Trigger>
            <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                <Setter Property="Background" Value="#3c3c3c"></Setter>
                <Setter Property="Foreground" Value="#ffffff"></Setter>
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Margin" Value="0"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

현재 ListViewItem에 AlternationCount 를 2를 줘서 리스트에 입력 받을때마다 위 스타일에 맞게 백그라운드 색상이 교차되도록 쓰고있습니다. 근데 여기서 처음 실행 시켰을땐 아무것도 입력받지 않다보니깐 ListView가 휑 하더라구요 그래서 입력받을때가 아닌 평소에도 교차된 background로 보여주고싶은데 어떻게 해야하는지 알고싶습니다. 검색을 해봐도 제가 쓰던 방법으로만 나오는 것 같아 질문드립니다.

2 Likes

ListViewBackground 속성을 이용한 트릭

참고: wpf - Alternate Background ListBox empty rows colors? - Stack Overflow

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="800"
        Height="450"
        mc:Ignorable="d">
    <Window.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Height" Value="24" />
            <Style.Triggers>
                <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                    <Setter Property="Background" Value="#1e1e1e" />
                    <Setter Property="Foreground" Value="#ffffff" />
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="Margin" Value="0" />
                </Trigger>
                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                    <Setter Property="Background" Value="#3c3c3c" />
                    <Setter Property="Foreground" Value="#ffffff" />
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="Margin" Value="0" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <ListView AlternationCount="2">
        <ListView.Background>
            <VisualBrush TileMode="Tile" Viewport="0,1,10,48" ViewportUnits="Absolute">
                <VisualBrush.Visual>
                    <StackPanel Width="10">
                        <Rectangle Fill="#1e1e1e" Height="24"/>
                        <Rectangle Fill="#3c3c3c" Height="24"/>
                    </StackPanel>
                </VisualBrush.Visual>
            </VisualBrush>
        </ListView.Background>
        <ListViewItem>Item1</ListViewItem>
        <ListViewItem>Item2</ListViewItem>
        <ListViewItem>Item3</ListViewItem>
    </ListView>
</Window>

혹은 <ListView.Background> 부분에

<VisualBrush TileMode="Tile" Viewport="0,1,10,48" ViewportUnits="Absolute">
    <VisualBrush.Visual>
        <ItemsControl Width="10" AlternationCount="2">
            <ListViewItem BorderThickness="0"/>
            <ListViewItem BorderThickness="0"/>
        </ItemsControl>
    </VisualBrush.Visual>
</VisualBrush>

VisualBreushViewPort 속성을 지정해 줘야 하기 때문에 ListViewItemStyle에서 Height값을 미리 지정해주면 좋습니다.

4 Likes

감사합니다
혹시 visualBrush를 처음 써보면서 ListViewItme style에서 height값을 지정하라고 하셨는데
Height값 지정으로 리스트에 넣을때 리스크 크기가 정해지는걸로 아는데
VisualBrush에서는 ListViewItem에 지정한 크기가 아니라 ViewPort 수치조절? 로 따로 크기를 보여주는 것 같은데 맞나요?

2 Likes

Viewport 속성 값 0,1,10,48에서 마지막 48이 배경색을 가지는 2개의 사각형 패턴이 반복되는 크기를 나타내므로 ListViewItemHeight 값의 2배로 지정해야 합니다.
ListViewItem의 Font 크기 등에 따라 Height가 유동적으로 변경될 수 있기 때문에 저 48 값을 적절히 맞춰 주시거나 ListViewItemHeight 속성을 지정하고 이 값의 2배로 사용하시라는 뜻이었습니다.

4 Likes

아하 감사합니다!
제가 window.Resources에서 만든걸 호출하기 전에 미리 보여주기 용으로
VisualBrush를 통해서 임의(?)로 만들어논걸 미리 보여주고 리스트에 넣으면 이제 적용시킨 window.Resources가 위를 덮는 방식 인가보네요

2 Likes

혹시 질문이 있는데

이렇게 사용할경우 ListView의 Column뿐만 아니라 ListView의 Header 즉 전체가 반복 패턴으로 나오는거 아닌가요?

3 Likes

한번 해보시고 혹시 이상한 부분이 있으시면 캡쳐를 첨부해주세요.

2 Likes

헤더가 있을때는 헤더의 뒤쪽부분도 색이 변하는데 혹시 해결법이 있을까요?
11
딱 리스트 내용부분만 바뀌게 하고싶습니다

2 Likes
 <Window.Resources>
     <Style TargetType="{x:Type ListViewItem}">
         <Setter Property="Height" Value="24" />
         <Style.Triggers>
             <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                 <Setter Property="Background" Value="#1e1e1e" />
                 <Setter Property="Foreground" Value="#ffffff" />
                 <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                 <Setter Property="Margin" Value="0" />
             </Trigger>
             <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                 <Setter Property="Background" Value="#3c3c3c" />
                 <Setter Property="Foreground" Value="#ffffff" />
                 <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                 <Setter Property="Margin" Value="0" />
             </Trigger>
         </Style.Triggers>
     </Style>
 </Window.Resources>

 <ListView AlternationCount="2">
     <ListView.Background>
         <VisualBrush
             TileMode="Tile"
             Viewport="0,1,10,48"
             ViewportUnits="Absolute">
             <VisualBrush.Visual>
                 <StackPanel Width="10">
                     <Rectangle Height="24" Fill="#1e1e1e" />
                     <Rectangle Height="24" Fill="#3c3c3c" />
                 </StackPanel>
             </VisualBrush.Visual>
         </VisualBrush>
     </ListView.Background>
     <ListView.View>
         <GridView>
             <GridViewColumn Header="Nam1" />
             <GridViewColumn Header="Nam2" />
         </GridView>
     </ListView.View>
     <ListView.Style>
         <Style TargetType="{x:Type ListView}">
             <Setter Property="Template">
                 <Setter.Value>
                     <ControlTemplate TargetType="{x:Type ListView}">
                         <Border Padding="0">
                             <Grid>
                                 <Grid.RowDefinitions>
                                     <RowDefinition Height="50" />
                                     <RowDefinition Height="*" />
                                 </Grid.RowDefinitions>
                                 <Grid Background="red">
                                     <GridViewHeaderRowPresenter Columns="{Binding Path=View.Columns, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}" />
                                 </Grid>
                                 <Grid Grid.Row="1" Background="{TemplateBinding Background}">
                                     <ItemsPresenter />
                                 </Grid>
                             </Grid>
                         </Border>
                     </ControlTemplate>
                 </Setter.Value>
             </Setter>
         </Style>
     </ListView.Style>
     <ListViewItem>Item1</ListViewItem>
     <ListViewItem>Item2</ListViewItem>
     <ListViewItem>Item3</ListViewItem>
 </ListView>

원하시는게 이게 맞을까요~?

3 Likes

어 맞습니다~ 감사합니다

이제 사용하던거에 수정해서 만들어봐야겠네요!

2 Likes

질문이 있는데 제가

<Setter Property="Template">
                 <Setter.Value>
                     <ControlTemplate TargetType="{x:Type ListView}">
                         <Border Padding="0">
                             <Grid>
                                 <Grid.RowDefinitions>
                                     <RowDefinition Height="50" />
                                     <RowDefinition Height="*" />
                                 </Grid.RowDefinitions>
                                 <Grid Background="red">
                                     <GridViewHeaderRowPresenter Columns="{Binding Path=View.Columns, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}" />
                                 </Grid>
                                 <Grid Grid.Row="1" Background="{TemplateBinding Background}">
                                     <ItemsPresenter />
                                 </Grid>
                             </Grid>
                         </Border>
                     </ControlTemplate>
                 </Setter.Value>
             </Setter>

이 부분을 이제 따로 만들어둔 ListView 스타일에다가 집어넣고 적용시켰는데
모양은 잘 나오더라구요 근데 Template를 건들여서 그런지 스크롤바를 Auto로 해놓고
d:ItemsSource="{d:SampleData ItemCount=11 를 아무리 많이 해도 스크롤바가 안 생기더라구요
전에는 ListView의 기본 템플릿을 리소스사전에 전부 가져와서 필요부분만 수정해서 쓰쓸때는 나왔는데 혹시 스크롤바를 오른쪽이랑 아래 나오게 할려면 어딜 수정해야할까요?

<Style x:Key="ScrollBarStyle1" TargetType="{x:Type ScrollBar}">
    <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="false"/>
    <!--<Setter Property="Background" Value="{StaticResource ScrollBar.Static.Background}"/>-->
    <Setter Property="Background" Value="#14171D"/>
    <Setter Property="BorderBrush" Value="#000000"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="BorderThickness" Value="0,2,0,0"/>
    <!--<Setter Property="Width" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>
    <Setter Property="MinWidth" Value="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/>-->
    <Setter Property="Margin" Value="0"/>
    <Setter Property="Width" Value="10"/>
    <Setter Property="MinWidth" Value="14"/>
    <Setter Property="Margin" Value="0,18,0,0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ScrollBar}">
                <Grid x:Name="Bg" SnapsToDevicePixels="true">
                    <!--<Grid.RowDefinitions>
                         -->
                    <!--스크롤바 크기 조절-->
                    <!--
                        <RowDefinition MaxHeight="13.2"/>
                        <RowDefinition Height="0.00001*"/>
                        <RowDefinition MaxHeight="0"/>
                    </Grid.RowDefinitions>-->
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Row="1"/>
                    <!--스크롤 위에 버튼 삭제 -->
                    <RepeatButton x:Name="PART_LineUpButton" Command="{x:Static ScrollBar.LineUpCommand}" IsEnabled="{TemplateBinding IsMouseOver}" Style="{StaticResource ScrollBarButton}" Visibility="Collapsed">
                        <Path x:Name="ArrowTop" Data="M 0,4 C0,4 0,6 0,6 0,6 3.5,2.5 3.5,2.5 3.5,2.5 7,6 7,6 7,6 7,4 7,4 7,4 3.5,0.5 3.5,0.5 3.5,0.5 0,4 0,4 z" Fill="{StaticResource ScrollBar.Static.Glyph}" Margin="3,4,3,3" Stretch="Uniform"/>
                    </RepeatButton>
                    <Track x:Name="PART_Track" IsDirectionReversed="true" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="1">
                        <Track.DecreaseRepeatButton>
                            <RepeatButton Command="{x:Static ScrollBar.PageUpCommand}" Style="{StaticResource RepeatButtonTransparent}" Visibility="Collapsed"/>
                        </Track.DecreaseRepeatButton>
                        <Track.IncreaseRepeatButton>
                            <RepeatButton Command="{x:Static ScrollBar.PageDownCommand}" Style="{StaticResource RepeatButtonTransparent}" Visibility="Collapsed"/>
                        </Track.IncreaseRepeatButton>
                        <Track.Thumb>
                            <Thumb Style="{StaticResource ScrollBarThumbVertical}"/>
                        </Track.Thumb>
                    </Track>
                    <!--스크롤 아래 버튼 삭제-->
                    <RepeatButton x:Name="PART_LineDownButton" Command="{x:Static ScrollBar.LineDownCommand}" IsEnabled="{TemplateBinding IsMouseOver}" Grid.Row="2" Style="{StaticResource ScrollBarButton}" Visibility="Collapsed">
                        <Path x:Name="ArrowBottom" Data="M 0,2.5 C0,2.5 0,0.5 0,0.5 0,0.5 3.5,4 3.5,4 3.5,4 7,0.5 7,0.5 7,0.5 7,2.5 7,2.5 7,2.5 3.5,6 3.5,6 3.5,6 0,2.5 0,2.5 z" Fill="{StaticResource ScrollBar.Static.Glyph}" Margin="3,4,3,3" Stretch="Uniform"/>
                    </RepeatButton>
                </Grid>
                <ControlTemplate.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineDownButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineDownButton}" Value="true"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowBottom" Value="{StaticResource ScrollBar.Pressed.Glyph}"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineUpButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineUpButton}" Value="true"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowTop" Value="{StaticResource ScrollBar.Pressed.Glyph}"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineDownButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineDownButton}" Value="false"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowBottom" Value="{StaticResource ScrollBar.MouseOver.Glyph}"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineUpButton}" Value="true"/>
                            <Condition Binding="{Binding IsPressed, ElementName=PART_LineUpButton}" Value="false"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Fill" TargetName="ArrowTop" Value="{StaticResource ScrollBar.MouseOver.Glyph}"/>
                    </MultiDataTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Fill" TargetName="ArrowTop" Value="{StaticResource ScrollBar.Disabled.Glyph}"/>
                        <Setter Property="Fill" TargetName="ArrowBottom" Value="{StaticResource ScrollBar.Disabled.Glyph}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Orientation" Value="Horizontal">
            <Setter Property="Width" Value="Auto"/>
            <Setter Property="MinWidth" Value="0"/>
            <Setter Property="Height" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}"/>
            <Setter Property="MinHeight" Value="{DynamicResource {x:Static SystemParameters.HorizontalScrollBarHeightKey}}"/>
            <Setter Property="Height" Value="10"/>
            <Setter Property="MinHeight" Value="14"/>
            <Setter Property="BorderThickness" Value="0,1"/>
            <Setter Property="Margin" Value="0,0,0,0"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollBar}">
                        <Grid x:Name="Bg" SnapsToDevicePixels="true">
                            <!--<Grid.ColumnDefinitions>
                                -->
                            <!--Horizontal 스크롤바 크기 조절-->
                            <!--
                                <ColumnDefinition MaxWidth="13.2"/>
                                <ColumnDefinition Width="0.00001*"/>
                                <ColumnDefinition MaxWidth="0"/>
                            </Grid.ColumnDefinitions>-->
                            <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1"/>
                            <RepeatButton x:Name="PART_LineLeftButton" Command="{x:Static ScrollBar.LineLeftCommand}" IsEnabled="{TemplateBinding IsMouseOver}" Style="{StaticResource ScrollBarButton}" Visibility="Collapsed">
                                <Path x:Name="ArrowLeft" Data="M 3.18,7 C3.18,7 5,7 5,7 5,7 1.81,3.5 1.81,3.5 1.81,3.5 5,0 5,0 5,0 3.18,0 3.18,0 3.18,0 0,3.5 0,3.5 0,3.5 3.18,7 3.18,7 z" Fill="{StaticResource ScrollBar.Static.Glyph}" Margin="3" Stretch="Uniform"/>
                            </RepeatButton>
                            <Track x:Name="PART_Track" Grid.Column="1" IsEnabled="{TemplateBinding IsMouseOver}">
                                <Track.DecreaseRepeatButton>
                                    <RepeatButton Command="{x:Static ScrollBar.PageLeftCommand}" Style="{StaticResource RepeatButtonTransparent}"/>
                                </Track.DecreaseRepeatButton>
                                <Track.IncreaseRepeatButton>
                                    <RepeatButton Command="{x:Static ScrollBar.PageRightCommand}" Style="{StaticResource RepeatButtonTransparent}"/>
                                </Track.IncreaseRepeatButton>
                                <Track.Thumb>
                                    <Thumb Style="{StaticResource ScrollBarThumbHorizontal}"/>
                                </Track.Thumb>
                            </Track>
                            <RepeatButton x:Name="PART_LineRightButton" Command="{x:Static ScrollBar.LineRightCommand}" Grid.Column="2" IsEnabled="{TemplateBinding IsMouseOver}" Style="{StaticResource ScrollBarButton}" Visibility="Collapsed">
                                <Path x:Name="ArrowRight" Data="M 1.81,7 C1.81,7 0,7 0,7 0,7 3.18,3.5 3.18,3.5 3.18,3.5 0,0 0,0 0,0 1.81,0 1.81,0 1.81,0 5,3.5 5,3.5 5,3.5 1.81,7 1.81,7 z" Fill="{StaticResource ScrollBar.Static.Glyph}" Margin="3" Stretch="Uniform"/>
                            </RepeatButton>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineRightButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineRightButton}" Value="true"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowRight" Value="{StaticResource ScrollBar.Pressed.Glyph}"/>
                            </MultiDataTrigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineLeftButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineLeftButton}" Value="true"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowLeft" Value="{StaticResource ScrollBar.Pressed.Glyph}"/>
                            </MultiDataTrigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineRightButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineRightButton}" Value="false"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowRight" Value="{StaticResource ScrollBar.MouseOver.Glyph}"/>
                            </MultiDataTrigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsMouseOver, ElementName=PART_LineLeftButton}" Value="true"/>
                                    <Condition Binding="{Binding IsPressed, ElementName=PART_LineLeftButton}" Value="false"/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Fill" TargetName="ArrowLeft" Value="{StaticResource ScrollBar.MouseOver.Glyph}"/>
                            </MultiDataTrigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Fill" TargetName="ArrowLeft" Value="{StaticResource ScrollBar.Disabled.Glyph}"/>
                                <Setter Property="Fill" TargetName="ArrowRight" Value="{StaticResource ScrollBar.Disabled.Glyph}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>

위에 코드는 제가 쓰던 스크롤바 스타일 입니다. ListView스타일에 따로 설정한거라곤 Width랑 heigth 두개 및 템플에 위에적힌 것만 수정해서 썼습니다.

2 Likes

아 예제 샘플소스로만 하다보니 신경을 못썼네여
Template 부분에 있는 ItemsPresenter만 출력되어있는데 ScrollViewer를 추가해주셔야합니다.

<ScrollViewer>  // ScrollViewer를 감싸주셔야합니다.
   <ItemsPresenter />
</ScrollViewer>
1 Like

아 감사합니다!
간단한거였네요

3 Likes