Change ListView CellTemplate based on state of item
I have a ListView that is has an ObservableCollection as its ItemsSource, and it has several columns. One of these is a State column which, depending on the current state of the item, shows a different message. Currently this is implemented as a basic string, and while it works it is far from pretty or userfriendly. I want to be able to vary the sort of output to more properly suit the state of the item.
I did do some research and know that I need to use a CellTemplate to affect the display, but all the different sorts of templates simply overwhelm me to the point where I can't figure out where to go next.
My code (excluding lots of other listview fluff) is as follows:
<ListView Name="itemsListView" ItemsSource="{Binding Source={StaticResource listingDataView}}" IsSynchronizedWithCurrentItem="True">
...
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Item Information">
...
<GridViewColumn DisplayMemberBinding="{Binding Path=StatusMessage}" Width="283" Header="Status" HeaderContainerStyle="{StaticResource GVHeaderLeftAlignedStyle}" />
</GridView>
</ListView.View>
</ListView>
Yes, the items have hardcoded 'Status Message' that get updated alongside other properties that are actually relevant for the code, causing ugly duplication elsewhere in my code. (And yes, I know this is far from pretty, but I want to improve this too.) That property would be called ItemState
as I am not all that creative.
So, my question is: how can I vary this column to have the most suitable display for开发者_运维百科 the given state? Textual descriptions will do for many states, but some are rather lengthy and might profit from a text with a progress bar besides it, and maybe some sort of time remaining. Another state would profit from having a clickable hyperlink. In other words, I think I need at least 3 different CellTemplates.
I realize it is a rather open-ended question that largely suffers from the design mistakes of someone (=me) who has rather little experience with WPF, but that is exactly why I'm hoping someone experienced can set me straight with some basic code before I make an even worse mess of things than I have already. :)
You can use triggers to change the content of the cell, e.g.
<GridViewColumn Header="Status">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding StateItem.HasError}" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<!-- Possibly create another contentcontrol which differentiates between errors -->
<DataTemplate>
<TextBlock Text="{Binding StateItem.Error}"
Foreground="Red"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding StateItem.HasError}" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="Images/Default.ico"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Code gets a bit crazy that way though if you branch it further but it's a way to do it.
Edit: The setters should set the ContentTemplate
instead of the Content
, apparently otherwise no new controls may be created and only one row shows the proper content since the content can only have one parent.
精彩评论