Fixed-Width Column in ListView: A Column that cannot be resized

A fixed-width column is a column that cannot be resized by mouse dragging or double-clicks. You can find instances in outlook. Currently two methods can be used to achieve the effect. One is to restyle GridViewColumnHeader to remove the gripper inside its Template. The other is to subclass GridViewColumn to restrict columns' width to a fixed size. Today's topic is about the second solution. The resulting column is a little bit different from the restyling one because there is still a gripper inside GridViewColumnHeader. When mouse is over the gap between columns, the cursor is still changed to the resizing cursor.

The main WPF elements we are going to cover in this session are GridViewColumn, dependency property definition, dependency property coercion.

 Step 1. Subclass GridViewColumn

The key in this step is to override WidthProperty's metadata to make it call CoerceWidth() to coerce its value when a new value is available.

public class FixedWidthColumn : GridViewColumn {

    static FixedWidthColumn() {

        WidthProperty.OverrideMetadata(typeof(FixedWidthColumn),

            new FrameworkPropertyMetadata(null, new CoerceValueCallback(OnCoerceWidth)));

}

private static object OnCoerceWidth(DependencyObject o, object baseValue) {

        return baseValue;

    }

}

 Step 2. Add a dependency property FixedWidth

The FixedWidth is used to set column's fixed width in spite of whatever the column's width is. The keys in this step are:

1. Define a dependency property.

2. When FixedWidth is changed, it calls CoerceValue() to coerce Width into the new value.

public double FixedWidth {

    get { return (double)GetValue(FixedWidthProperty); }

    set { SetValue(FixedWidthProperty, value); }

}

public static readonly DependencyProperty FixedWidthProperty =

    DependencyProperty.Register(

        "FixedWidth",

  typeof(double),

        typeof(FixedWidthColumn),

        new FrameworkPropertyMetadata(double.NaN, new PropertyChangedCallback(OnFixedWidthChanged)));

private static void OnFixedWidthChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {

    FixedWidthColumn fwc = o as FixedWidthColumn;

    if (fwc != null)

        fwc.CoerceValue(WidthProperty);

}

Step 3. Rewrite CoerceWidth() to make it always return FixedWidth

Then the Width will always get the same value whatever value is set on Width.

private static object OnCoerceWidth(DependencyObject o, object baseValue) {

    FixedWidthColumn fwc = o as FixedWidthColumn;

    if (fwc != null)

        return fwc.FixedWidth;

    return baseValue;

}

Step 4. Use it in GridView

It is used like normal GridViewColumn.

<GridView xmlns:l="clr-namespace:FixedWidthColumnSample">

  <l:FixedWidthColumn Header="Coerce Fixed-Width Column"

                     DisplayMemberBinding="{Binding Name}"

                      FixedWidth="100"/>

</GridView>

 

 We're done!

 

This sample is based on the February CTP.

 

Declaimer: This posting is provided "AS IS" with no warranties, and confers no rights.

FixedWidthColumnSample.zip