简体   繁体   中英

Styling individual cells in a listview

On the internet I found many examples of styling a complete column or complete row in a listview.

I need to be able to dynamically style individual cells in the listview. How can I access the properties of individual items in a row?

If you've got a finite number of properties in your data objects that you want to use to style your items, you can create data templates and styles, and use data triggers to switch between them. I've used something like this to alter the appearance of data objects in a list based on if they are "active/inactive" and to create a collapsed/expanded version of the object based on whether it's selected or not.

You can also use converters (built-in or custom) to get some effects easily. For example, I used a built-in boolean to visibility converter to hide/unhide the combobox/textblock in my TaskSelectedTemplate based on if the object's IsActive member.

<DataTemplate x:Key="TaskSelectedTemplate">
    <Grid Margin="4">
        ...
        <Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 4 0"
                BorderThickness="0" 
                CornerRadius="2">
            <Border.Background>
                <MultiBinding Converter="{StaticResource ActiveToColor}">
                    <Binding Path="."/>
                    <Binding Path="IsActive"/>
                    <Binding Path="IsPaused"/>
                </MultiBinding>
            </Border.Background>
        </Border>

        <StackPanel Grid.Row="0" Grid.Column="1"
                    Orientation="Horizontal"
                    Margin="0 2">
            <ComboBox ItemsSource="{Binding Source={StaticResource TaskTypes}}"
                      SelectedItem="{Binding Type}"
                      Text="{Binding Type}"
                      Visibility="{Binding IsActive, Converter={StaticResource BoolToVis}}"/>
            <TextBlock Text="{Binding Type}"
                       FontWeight="Bold"
                       Visibility="{Binding IsActive, Converter={StaticResource InvBoolToVis}}"/>
            <TextBlock Text=" task"/>
        </StackPanel>
        ...
    </Grid>
</DataTemplate>

<DataTemplate x:Key="TaskNotSelectedTemplate">
    <Grid Margin="4">
        ...
        <Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 4 0"
                BorderThickness="0" 
                CornerRadius="2">
            <Border.Background>
                <MultiBinding Converter="{StaticResource ActiveToColor}">
                    <Binding Path="."/>
                    <Binding Path="IsActive"/>
                    <Binding Path="IsPaused"/>
                </MultiBinding>
            </Border.Background>
        </Border>

        <TextBlock Grid.Row="0" Grid.Column="1"
                   Text="{Binding Type}"/>
        <TextBlock Grid.Row="0" Grid.Column="2"
                   TextAlignment="Right">
                <Run Text="{Binding Length.TotalMinutes, StringFormat='0', Mode=OneWay}"/>
                <Run Text=" min"/>
            </TextBlock>
        <TextBlock Grid.Row="0" Grid.Column="3"
                   TextAlignment="Right">
                <Run Text="{Binding TimesPerformed, Mode=OneWay}"/>
                <Run Text=" tasks"/>
            </TextBlock>            
    </Grid>
</DataTemplate>

<Style x:Key="ContainerStyle" TargetType="{x:Type ListBoxItem}">
    <!--this part changes the selected item highlight color-->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Border Name="Border">
                    <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="Border" 
                                Property="Background" Value="#2000BFFF">
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <!--this part causes selected task to expand-->
    <Setter Property="ContentTemplate" Value="{StaticResource TaskNotSelectedTemplate}"/>
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource TaskSelectedTemplate}"/>
        </Trigger>
    </Style.Triggers>
</Style>

For more complex scenarios, you might want to look at DataTemplateSelector . I've never used it, but it seems like it might be ideal if you've got a lot of data templates to juggle.

Generally speaking, you shouldn't need this. Assuming you are using GridView , you should be able to use CellTemplate or CellTemplateSelector of your GridViewColumn s.

If you really want to access specific cells, I think there is no clean way, you'd be better using DataGrid (from.Net 4 or WPF toolkit for.Net 3.5). With that, you can do something like this:

((TextBlock)datagrid.Columns[1].GetCellContent(m_specificItem)).Background = Brushes.Red

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM