WPF - How to center column data in ListView?
I'm still learning WPF, but I'm really confused about something that should be really simple. What I want to do is to center the contents of the 3rd and 4th columns. When I run this, the columns are left justified:
<ListView Margin="0" x:Name="listMonitoredUrls" AlternationCount="1"
ItemsSource="{Binding}" >
<ListView.View>
<GridView>
<GridViewColumn Header="Description" DisplayMemberBinding="{Binding FriendlyDesc}"/>
<GridViewColumn Header="Url" DisplayMemberBinding="{Binding Url}"/>
<GridViewColumn Header="Frequency">
<GridViewColumn.CellTemplate >
<DataTemplate>
<TextBlock Text="{Binding ScanFrequencyMinutes}"
HorizontalAlignment="Center"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Next Scan" >
<GridViewColumn.CellTemplate >
<DataTemplate>
<TextB开发者_如何学JAVAlock Text="{Binding TimeNextScanStr}"
HorizontalAlignment="Center"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I"m really starting to like WPF, but some simple things like this seem to be really hard.
Try using the TextAlignment
property instead of HorizontalAlignment
- should do it.
To my understanding HorizontalAlignment="Center"
will center your textblock not the text in it.
This might be a long shot but i've had to do it for listboxes where the items are defined by templates. Try setting the HorizontalContentAlignment="Stretch" on your ListView. If I don't set that the items take only as much space as they need and are left justified.
I've created a solution which works under the common scenario of:
<GridViewColumn Header="Some Property" DisplayMemberBinding="{Binding SomeProperty}" />
where one only wants a simple DisplayMemberBinding
with text without having to specify a CellTemplate
the new code uses an attached property and becomes:
<GridViewColumn Header="Some Property" DisplayMemberBinding="{Binding SomeProperty}"
ctrl:GridViewExtensions.IsContentCentered="True" />
attached property code:
public static class GridViewExtensions
{
#region IsContentCentered
[Category("Common")]
[AttachedPropertyBrowsableForType(typeof(GridViewColumn))]
public static bool GetIsContentCentered(GridViewColumn gridViewColumn)
{
return (bool)gridViewColumn.GetValue(IsContentCenteredProperty);
}
public static void SetIsContentCentered(GridViewColumn gridViewColumn, bool value)
{
gridViewColumn.SetValue(IsContentCenteredProperty, value);
}
public static readonly DependencyProperty IsContentCenteredProperty =
DependencyProperty.RegisterAttached(
"IsContentCentered",
typeof(bool), // type
typeof(GridViewExtensions), // containing type
new PropertyMetadata(default(bool), OnIsContentCenteredChanged)
);
private static void OnIsContentCenteredChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
OnIsContentCenteredChanged((GridViewColumn)d, (bool)e.NewValue);
}
private static void OnIsContentCenteredChanged(GridViewColumn gridViewColumn, bool isContentCentered)
{
if (isContentCentered == false) { return; }
// must wait a bit otherwise GridViewColumn.DisplayMemberBinding will not yet be initialized,
new DispatcherTimer(TimeSpan.FromMilliseconds(100), DispatcherPriority.Normal, OnColumnLoaded, gridViewColumn.Dispatcher)
{
Tag = gridViewColumn
}.Start();
}
static void OnColumnLoaded(object sender, EventArgs e)
{
var timer = (DispatcherTimer)sender;
timer.Stop();
var gridViewColumn = (GridViewColumn)timer.Tag;
if (gridViewColumn.DisplayMemberBinding == null)
{
throw new Exception("Only allowed with DisplayMemberBinding.");
}
var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
textBlockFactory.SetBinding(TextBlock.TextProperty, gridViewColumn.DisplayMemberBinding);
textBlockFactory.SetValue(TextBlock.TextAlignmentProperty, TextAlignment.Center);
var cellTemplate = new DataTemplate { VisualTree = textBlockFactory };
gridViewColumn.DisplayMemberBinding = null; // must null, otherwise CellTemplate won't be recognized
gridViewColumn.CellTemplate = cellTemplate;
}
#endregion IsContentCentered
}
Here is my example to show a working xaml:
<Window x:Class="WPF_Tutorial.Rich_text_controls.BlockUIContainerCenteredColumnSample"
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"
mc:Ignorable="d"
xmlns:self="clr-namespace:WPF_Tutorial.Rich_text_controls"
Title="BlockUIContainerCenteredColumnSample" Height="275" Width="300"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<x:Array x:Key="UserArray" Type="{x:Type self:User}">
<self:User Name="John Doe" Age="42" />
<self:User Name="Jane May-Anne Josephine Renalds Doe" Age="36" />
</x:Array>
</Window.Resources>
<Grid>
<FlowDocumentScrollViewer>
<FlowDocument>
<Paragraph FontSize="36" Margin="0">Users</Paragraph>
<Paragraph FontStyle="Italic" TextAlignment="Left" FontSize="14" Foreground="Gray">Here's a list of our users, inside our FlowDocument, in a completely interactive ListView control!</Paragraph>
<BlockUIContainer>
<ListView BorderThickness="0" ItemsSource="{StaticResource UserArray}" HorizontalAlignment="Center">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<!-- This stretches out the TextBlock width to the column width -->
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="150" />
<GridViewColumn>
<GridViewColumnHeader Content="Age" Width="75" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Age}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</BlockUIContainer>
<Paragraph FontStyle="Italic" TextAlignment="Left" FontSize="14" Foreground="Gray">More content can go here...</Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
</Grid>
</Window>
Notice the <ListView.ItemContainerStyle>
block. It has the <Setter ...
.
Without this, as per AndyG's text, nothing will work the way you want.
This has been very frustrating trying to work out.
By the way, here is the backing-code for this xaml:
namespace WPF_Tutorial.Rich_text_controls
{
using System.Windows;
public partial class BlockUIContainerCenteredColumnSample : Window
{
public BlockUIContainerCenteredColumnSample()
{
InitializeComponent();
}
}
public class User
{
public int Age { get; set; }
public string Name { get; set; }
}
}
What you should see when run
精彩评论