WPF ListView with Check Boxes and No Clipping
Do you need a simple data-bound WPF ListView with check boxed items without text trimming ellipsis and without header columns? I very often do. In this blog, I would like to share with you a simple way to build this control that I call CheckBoxListView.
What We Want
What We Don't Want
What We Need to Do
<ListView Name="myListView">
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility"
Value="Collapsed"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Margin="0"
VerticalAlignment="Center"
IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<TextBlock Margin="0"
Text="{Binding Text}"
Loaded="TextBlock_Loaded"/>
</GridView>
</ListView.View>
</ListView>
...
private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
GridView gridView = myListView.View as GridView;
if (gridView != null && gridView.Columns.Count >= 2)
// Calculate the item's desired text width and increase the
// text column's width to match the widest text
TextBlock tb = (TextBlock)sender;
tb.Measure(new Size(Double.MaxValue, Double.MaxValue));
double newWidth = tb.DesiredSize.Width;
GridViewColumnCollection columns = gridView.Columns;
if (newWidth > columns[1].Width ||
double.IsNaN(columns[1].Width))
columns[1].Width = newWidth;
}
// Remove the text block cell's content presenter built-in
// margin for better-looking spacing
ContentPresenter contentPresenter = VisualTreeHelper.GetParent(tb) as ContentPresenter;
if (contentPresenter != null)
contentPresenter.Margin = new Thickness(0);
Hey, What About Data-Binding?
Even though there are a lot of resources on this topic, here is one way that you can encapsulate an item data source and bind the sources to the List View.
First define a class to hold the data for each list view item:
/// <summary>
/// Encapsulate item data source for a CheckBoxListView item
/// </summary>
public class CheckBoxListViewItemSource : INotifyPropertyChanged
public CheckBoxListViewItemSource(String text)
m_text = text;
public bool IsChecked
get { return m_checked; }
set
if (m_checked == value) return;
m_checked = value;
RaisePropertyChanged("Checked");
public String Text
get { return m_text; }
if (m_text == value) return;
m_text = value;
RaisePropertyChanged("Text");
public override string ToString()
return Text;
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propName)
PropertyChangedEventHandler eh = PropertyChanged;
if (eh != null)
eh(this, new PropertyChangedEventArgs(propName));
private bool m_checked;
private String m_text;
Then create a list to hold those item data sources:
In the following sample, I created this list in the constructor of the application window.
public Window1()
InitializeComponent();
// Fill the list via data-bound item sources
ObservableCollection<CheckBoxListViewItemSource> itemSources = new ObservableCollection<CheckBoxListViewItemSource>();
myListView.ItemsSource = itemSources;
int ii = 1;
for (int i = 0; i < 10; i++)
itemSources.Add(new CheckBoxListViewItemSource(String.Format("Short Item {0}", ii++)));
for (int i = 0; i < 5; i++)
itemSources.Add(new CheckBoxListViewItemSource(String.Format("Long Item {0} with long long long long long long long long long text", ii++)));
Then bind that list to the List View:
That's it for now. Next time, we'll look at a way to set focus to a list view item.
-Tan