3

I want to create a style for my ListViews in my WPF app, which makes them appear more like the Windows Explorer ListView. The thing I am stuck on is the ellipsis (...) that appears in the Grid/Details view when a column is too narrow to fix the text.

I know I can override the cell template of each column, and explicitly set the TextTrimming mode to get ellipsis on a per-column basis. However, I want a style that I can apply to any ListView to get the same behavior.

I want to be able to define the listview like this:

<ListView ItemsSource="{Binding Library}" Style="{StaticResource ExplorerListStyle}">
    <ListView.View>
        <GridView>
           <GridViewColumn Width="90" Header="Title" DisplayMemberBinding="{Binding Title}" />
           <GridViewColumn Width="60" Header="Author" DisplayMemberBinding="{Binding Author}" />
        </GridView>
    </ListView.View>
</ListView>

I also want to be able to override the cell template for some columns, e.g. to set the text color, ideally while still inheriting the TextTrimming mode for the text in the template.

The only way I have managed to achieve this so far is to explicitly override the TextBlock style inside the ListView:

<ListView ItemsSource="{Binding Library}">
    <ListView.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="TextTrimming" Value="CharacterEllipsis" />
        </Style>
    </ListView.Resources>
    <ListView.View>
        <GridView>
           <GridViewColumn Width="90" Header="Title" DisplayMemberBinding="{Binding Title}" />
           <GridViewColumn Width="60" Header="Author" DisplayMemberBinding="{Binding Author}" />
        </GridView>
    </ListView.View>
</ListView>

However, this seems a bit heavy handed, and it's not possible, as far as I can tell, to set this in a style.

So, I'm looking for another way to set the TextTrimming mode for a GridViewColumns header and cells, that can be set in a style, and doesn't require explicit CellTemplates.

Thanks,

Mark

Mark
  • 1,784
  • 16
  • 26
  • Perhaps you could define your datatemplate with the DataType property, then that data template would be used automatically for an object of that type (unless you specifically specify otherwise). See http://msdn.microsoft.com/en-us/library/ms742521.aspx#Styling_DataType – Brandorf Apr 04 '12 at 15:02
  • That won't work, because the things in each column are simple strings. – Mark Apr 26 '12 at 08:01
  • Not the answer you're looking for but I used http://stackoverflow.com/a/4401594/492 - it does't do the header but I wasn't after that. Just dropping it here as an alternative for Googlers – CAD bloke Feb 08 '15 at 22:51

1 Answers1

0

Well, I thought of a super hacky way of doing this. I'm kind of a novice, so I'm sure this can be improved upon, but...I set the ListView's Template in a Style, and then on the first Border element inside that template I add a Loaded event, and in that Loaded event I construct the TextTrimming TextBlock style and add it to the ListView's Resources, with the following code:

private void ListView_Loaded(object sender, RoutedEventArgs e)
{
    var ListViewTextBlockStyle = new Style
    {
        TargetType = typeof(TextBlock)
    };

    ListViewTextBlockStyle.Setters.Add(new Setter(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis));

    ListView listView = (ListView)VisualTreeHelper.GetParent((Border)sender);

    listView.Resources.Add(typeof(TextBlock), ListViewTextBlockStyle);
}

Note that this targets the border and uses VisualTreeHelper to get the parent ListView; I didn't see a way to add events directly to the ListView from the Style (perhaps there is, but idk) so I had to piggyback on the border. Also note it doesn't work if you're directly adding <ListViewItem>s in the XAML, it works when you specify an ItemsSource and have the GridViewColumns bind to attributes in elements of that source.

Like I said, insanely hacky, but it does work.

Malurth
  • 49
  • 6