devuxer
devuxer

Reputation: 42354

Is there any way to temporarily detach a binding in WPF?

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!

Upvotes: 2

Views: 2219

Answers (1)

devuxer
devuxer

Reputation: 42354

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

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.

Upvotes: 3

Related Questions