19

Does anyone know if there is an option to hide a GridViewColumn somehow like this:

<ListView.View>
    <GridView>
        <GridViewColumn Header="Test" IsVisible="{Binding Path=ColumnIsVisible}" />
    </GridView>
<ListView.View>

Thanks a lot!

Edit: For clarity

Unfortunately, there is no "IsVisible" Property. I'm looking for a way to create that.

Edit: The solution based on the feedback looks like:

<GridViewColumn DisplayMemberBinding="{Binding Path=OptionColumn1Text}" 
                Width="{Binding Path=SelectedEntitiy.OptionColumn1Width}">
    <GridViewColumnHeader Content="{Binding Path=SelectedEntitiy.OptionColumn1Header}" IsEnabled="{Binding Path=SelectedEntitiy.OptionColumn1Width, Converter={StaticResource widthToBool}}" />
</GridViewColumn>

public class WidthToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value > 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Thanks to all!
Cheers

Joseph jun. Melettukunnel
  • 6,267
  • 20
  • 69
  • 90

6 Answers6

13

Edit: Reflecting the modified question.

What about creating a 0 width column? Write a Boolean to Width IValueConverter, that takes a ColumnIsVisible as the ConverterParmeter?

 public class BooleanToWidthConverter : IValueConverter {
        public object Convert(object value, Type targetType, 
                              object parameter, CultureInfo culture){
            return ((bool) parameter)? value : 0;
        }
 
        public object ConvertBack(object value, Type targetType, 
                                  object parameter, CultureInfo culture){
            throw new NotImplementedException();
        }
    }

Something like:

<ListView .. >
 <ListView.Resources>
  <BooleanToWidthConverter x:Key="boolToWidth" />
 </ListView.Resources>

 <ListView.View>
    <GridView>
        <GridViewColumn 
                  Header="Test" 
                  Width=
      "{Binding Path=ColumnWidth, 
                Converter={StaticResource boolToWidth}, 
                ConverterParameter=ColumnIsVisible}" />
    </GridView>
 <ListView.View>
Tim Rutter
  • 4,549
  • 3
  • 23
  • 47
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
8

Here is another solution based on setting the column's width to zero. I have modified it a little. It now works like this:

  1. Bind the header's visibility to a boolean property of the ViewModel, using a bool-to-visibility converter
  2. Use an attached property on the header to set the column's width to zero

Here is the code.

XAML:

<GridViewColumn
    HeaderTemplate="..." 
    HeaderContainerStyle="...">
    <GridViewColumnHeader 
        Content="Header text" 
        Visibility="{Binding AppliesToColumnVisible, Converter={StaticResource BooleanToVisibilityConverter}}" 
        behaviors:GridViewBehaviors.CollapseableColumn="True" />

BooleanToVisibilityConverter:

public class BooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool param = bool.Parse(value.ToString());
        if (param == true)
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Attached behavior GridViewBehaviors.CollapseableColumn:

public static readonly DependencyProperty CollapseableColumnProperty =
     DependencyProperty.RegisterAttached("CollapseableColumn", typeof(bool), typeof(GridViewBehaviors),
    new UIPropertyMetadata(false, OnCollapseableColumnChanged));

public static bool GetCollapseableColumn(DependencyObject d)
{
    return (bool)d.GetValue(CollapseableColumnProperty);
}

public static void SetCollapseableColumn(DependencyObject d, bool value)
{
    d.SetValue(CollapseableColumnProperty, value);
}

private static void OnCollapseableColumnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
    GridViewColumnHeader header = sender as GridViewColumnHeader;
    if (header == null)
        return;

    header.IsVisibleChanged += new DependencyPropertyChangedEventHandler(AdjustWidth);
}

static void AdjustWidth(object sender, DependencyPropertyChangedEventArgs e)
{
    GridViewColumnHeader header = sender as GridViewColumnHeader;
    if (header == null)
        return;

    if (header.Visibility == Visibility.Collapsed)
        header.Column.Width = 0;
    else
        header.Column.Width = double.NaN;   // "Auto"
}
thatguy
  • 21,059
  • 6
  • 30
  • 40
Helge Klein
  • 8,829
  • 8
  • 51
  • 71
  • Nice. I put this into the code-behind my custom control, and "GridViewBehaviors" becomes the control class name. Note you'll get intellisense errors until the code-behind is compiled the first time. – Andrew Roberts Jul 27 '23 at 11:46
1

You could remove it programmatically:

If you know the name of the header:

RemoveHeaderByName(listView, "Your Header Name");

private bool RemoveHeaderByName(ListView listView, string headerName)
{
    GridView gridView = listView?.View as GridView;
    if (gridView != null)
    {
        foreach(var column in gridView?.Columns)
        {
            if (column.Header as string == headerName)
            {
                if(gridView.Columns.Remove(column))
                    return true;
            }
        }
        return false;
    }
}

Or if you know the index of the header (it is better if the header name can be changed for example if you have localized application):

private bool RemoveHeaderByPosition(ListView listView, int position)
{
    GridView gridView = listView?.View as GridView;
    if (gridView != null && position >= gridView.Columns.Count-1)
    {
        var columnToRemove = gridView.Columns[position];
        if (gridView.Columns.Remove(columnToRemove))
            return true;
    }
    return false;
}
75ntamas
  • 123
  • 5
0

I've set the column the width="0". Now the column looks like its not visible. But i do not know if it will affect anything else. It might be a dummy solution but for now it works.

Munawir
  • 3,346
  • 9
  • 33
  • 51
hyphestos
  • 61
  • 1
  • 5
0

One simpler approach, that still uses the concept of setting the columns width to zero but does not have the side effects of using a IValueConverter (the user can still drag the column wider) is to create a new getter/setter that returns a width based on your ColumnIsVisible variable and then bind to that:

public double ColumnWidth
{
    get
    {
        if (this.ColumnIsVisible)
        {
            return 100;
        }
        else
        {
            return 0;
        }
    }

    set
    {
        OnPropertyChanged("ColumnWidth");
    }
}

Make your bindings TwoWay and if the user attempts to drag the column wider OnPropertyChanged will be called and reset the width to 0. You might have to use a binding proxy though for your binding. Also add a call to OnPropertyChanged("ColumnWidth") when ever ColumnIsVisible is updated :)

stuicidle
  • 297
  • 1
  • 8
-1

Use if Thumb.DragDelta may solve the problem

I use it in listview as

<ListView x:Name="MyListView"IsSynchronizedWithCurrentItem="True"   
      ItemsSource="{Binding Path=Items}",  Mode=Default, Source={StaticResource DataProvider}}" 
      Thumb.DragDelta="Thumb_DragDelta">


public Window1()
{   
InitializeComponent(); 
MyListView.AddHandler(Thumb.DragDeltaEvent, new DragDeltaEventHandler(Thumb_DragDelta), true );

void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{  
 Thumb senderAsThumb = e.OriginalSource as Thumb;    
 GridViewColumnHeader header = senderAsThumb.TemplatedParent as GridViewColumnHeader;     
 if (header.Column.ActualWidth < MIN_WIDTH)   
 {   
    header.Column.Width = MIN_WIDTH;  
 }  
 if (header.Column.ActualWidth > MAX_WIDTH)     
 {      
    header.Column.Width = MAX_WIDTH;   
 }
}
}
Sauron
  • 16,668
  • 41
  • 122
  • 174