C#/WPF: Make a GridViewColumn Visible=false?
Asked Answered
D

7

19

Is there an option to hide a GridViewColumn somehow like this:

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

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();
    }
}
Dentelle answered 8/9, 2009 at 8:54 Comment(0)
I
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>
Itinerary answered 8/9, 2009 at 8:59 Comment(6)
Thanks for the quick response. Unfortunately, there is no "IsVisible" Property.. so I'm looking for a way to create that.Dentelle
Comment to your edit: That would stil allow the user to resize the column, unfortunately there isn't a Enabled-Property either.Dentelle
@Joseph : there is no IsEnabled property on the GridViewColumn itself, but there is one on the GridViewColumnHeader (which inherits from ButtonBase). So you could set IsEnabled in the HeaderContainerStyleEvadne
+1 for setting the column width to 0. See my response for a variant of this using an attached behavior.Mileage
Setting width to 0 will still make it extendible hence bringing it back on the UI.Zonnya
@Zonnya worse; by manually extending the column width after it's been set to 0, the binding breaks.Kellsie
M
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"
}
Mileage answered 2/4, 2011 at 23:17 Comment(1)
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.Blowtube
B
2

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;
}
Bertold answered 13/3, 2023 at 9:7 Comment(1)
A warning about manipulating the GridView Columns programmatically. It's very convenient, you can remove, insert, or move columns programmatically by manipulating the content of this ObservableCollection. However, any column added to the collection after the grid has been display will disrupt the list virtualization, and lead to noticeable performance degradation during scrolling.Yean
M
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.

Melchizedek answered 17/12, 2014 at 10:45 Comment(1)
User can still drag the column widthCanescent
O
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 :)

Oler answered 30/5, 2018 at 8:48 Comment(0)
W
0

I chose to create a new class to save the state of the GridView, and then manually update the state of the original list when the state changes, which is equivalent to removing it when it is invisible, rather than hiding it.

           foreach (var item in ListViewVisibilitys.Where(x => x.IsVisibility==false).ToList())
            {
                gridView.Columns.Remove(item.gridViewColumn);
            }
            var lists = ListViewVisibilitys.Where(x => x.IsVisibility == true).ToList();
            for (int i = 0; i < lists.Count; i++)
            {
                var desiredColumn = lists[i].gridViewColumn;
                if (gridView.Columns.Contains(desiredColumn))
                {

                    var actualIndex = gridView.Columns.IndexOf(desiredColumn);
                    // 如果当前列的位置不正确,则将其移动到正确的位置
                    if (actualIndex != i)
                    {
                        gridView.Columns.Move(actualIndex, i);
                    }
                }
                else
                {
                    gridView.Columns.Insert(i, desiredColumn);
                }

            }
Welladvised answered 21/1, 2024 at 20:26 Comment(0)
D
-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;   
 }
}
}
Determiner answered 8/9, 2009 at 11:14 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.