views:

172

answers:

1

Background:

I have a ListView/GridView with several columns. In some situations, only some of the columns are shown. Since there is no Visible property for GridViewColumns in WPF, I set the width of the columns I want to hide to zero. Visually, this achieves the desired effect (and I actually modified the ControlTemplate for the GridViewColumnHeader so that it's impossible for the user to accidentally expand any hidden columns).

Problem:

The problem is that the bindings for the hidden columns are still in play, and they are trying to look up data that doesn't exist. In this case, it causes an IndexOutOfRangeException since it's trying to look up a column name that doesn't exist on the DataTable that it is bound to.

Question:

How can I temporarily disable or detach the binding for columns that are hidden? Or please suggest a better solution if you have one.

Thanks!

A: 

Ahh, I think I've got it. IValueConverter to the resue.

Here's the solution I came up with in case someone else has the same problem:

Step 1. Create a converter.

This IValueConverter checks whether the index was out of range, and if so, returns an empty string. Note that I use the converter's parameter to hold the column name.

public class DataRowViewToCellString : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        DataRowView row = (DataRowView)value;
        string columnName = (string)parameter;
        if (row.DataView.Table.Columns.Contains(columnName))
            return row[columnName].ToString();
        else
            return Binding.DoNothing;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}

Step 2. Throw the converter into a DataTemplate.

<local_converters:DataRowViewToCellString
    x:Key="TaskWindow_DataRowViewToCellString" />

<DataTemplate
    x:Key="TaskWindow_Column4Template">
    <TextBlock
        Text="{Binding Converter={StaticResource TaskWindow_DataRowViewToCellString}, ConverterParameter=Column4}" />
</DataTemplate>

Step 3. reference the template in the "sometimes hidden" GridViewColumn.

<ListView ... >
    <ListView.View>
        <GridView ... >
            ...
            <GridViewColumn
                Header="SometimesHiddenColumn"
                CellTemplate="{StaticResource TaskWindow_Column4Template}">
        </GridView>
    </ListView.View>
</ListView>

EDIT

Change the return value of the converter in cases where the column name is out of range from string.Empty to Binding.DoNothing per Dennis Roche's suggestion.

DanM
I agree that is a good solution to your problem. The only suggestion I would make is the change return String.Empty to return Binding.DoNothing.
Dennis Roche
Good idea, thanks!
DanM