How to hide DataGrid column in WPF automatically using MVVM?

58,190

Solution 1

If you want to hide the Column, you need to specify the Property Visibility like this,

YourDataGrid.Columns[IndexOftheColumn].Visibility = Visibility.Collapsed;

If you want to Hide the first column say "Network ID"

dg.Columns[0].Visibility = Visibility.Collapsed;

Solution 2

For those who are looking to hide it in XAML

it would look something like this:

<DataGridTextColumn Visibility="Collapsed" Header="Merchant Reference" Binding="{Binding MerchantReference}" Width="200" />

To do it in XAML rather than code one reason would be when you have a template that has extra column that does not apply to some cases, but you're lazy and don't want to make a separate template and backing class.
Another reason would be just for testing how would it look hidden.
Third to start as hidden and then make it visible in model with some trigger

Solution 3

You don't have to hide a column, just set its MaxWidth property to Zero and it wont appear.

        DataGrid.Columns[IndexOfColumn].MaxWidth = 0;

Solution 4

In MVVM this is typically handled via a ValueConverter

public sealed class BoolToVisibilityConverter : IValueConverter
{
   public Visibility TrueValue { get; set; }
   public Visibility FalseValue { get; set; }

   public BoolToVisibilityConverter()
   {
      // Set defaults
      this.TrueValue = Visibility.Visible;
      this.FalseValue = Visibility.Collapsed;
   }

   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
       bool flag = false;
       if (value is bool)
       {
          flag = (bool)value;
       }
       else if (value is bool?)
       {
          bool? nullable = (bool?)value;
          flag = nullable.HasValue ? nullable.Value : false;
      }
      return flag ? this.TrueValue : this.FalseValue;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
      if (object.Equals(value, this.TrueValue))
          return true;
      if (object.Equals(value, this.FalseValue))
        return false;
      return null;
  }
}

Because the DataGridTextColumn or any other supported dataGrid columns doesn't lie in Visual tree of DataGrid (see Binding Visibility for DataGridColumn in WPF) one need to add a binding Proxy

public class BindingProxy : Freezable
{
#region Overrides of Freezable

protected override Freezable CreateInstanceCore()
{
    return new BindingProxy();
}

#endregion

public object Data
{
    get { return (object)GetValue(DataProperty); }
    set { SetValue(DataProperty, value); }
}

public static readonly DependencyProperty DataProperty =
    DependencyProperty.Register("Data", typeof(object),
                                 typeof(BindingProxy));

}

In the resources section add

<ResourceDictionary>
   <namespace:BoolToVisibilityConverter x:Key="BoolToCollapsed" TrueValue="Visible" FalseValue="Collapsed" />
   <namespace:BindingProxy x:Key="Proxy" Data="{Binding}"/>
</ResourceDictionary>

And on you datagrid

 <DataGrid ItemsSource="{Binding Items}" >
    <DataGrid.Columns>
      <DataGridTextColumn Visibility="{Binding Data.ShowThisColumnFlag, Source={StaticResource Proxy}, Converter={StaticResource BoolToCollapsed}}" Binding="{Binding PropertyOne}" />

      <DataGridTextColumn Visibility="{Binding Data.ShowAnotherColumnFlag, Source={StaticResource Proxy}, Converter={StaticResource BoolToCollapsed}}" Binding="{Binding PropertyTwo}"/>
    </DataGrid.Columns>
 </DataGrid>

You should set your Mode as needed.

Thanks to Rohit Vats for BindingProxy post.

Share:
58,190
Sapper
Author by

Sapper

Updated on January 15, 2020

Comments

  • Sapper
    Sapper over 4 years

    Using MVVM (no code-behind), I want to hide my DataGrid columns upon selection, I have following code:

    <DataGrid ItemsSource="{Binding SSID}" Grid.Row="1"  Margin="10,10,0,0" Height="200" Width="500" Grid.ColumnSpan="2" Name="dg" HorizontalAlignment="Left" AutoGenerateColumns="False">
        <DataGrid.Columns>
          <DataGridTextColumn Header="Network ID" Binding="{Binding _networkID}"></DataGridTextColumn>
          <DataGridTextColumn Header="SSID" Binding="{Binding _ssid}"></DataGridTextColumn>
          <DataGridTextColumn Header="VLAN" Binding="{Binding _vlan}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _authenticationMode}" Binding="{Binding _authenticationMode}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _authentication}" Binding="{Binding _authentication}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _staticWEPKeyType}" Binding="{Binding _staticWEPKeyType}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _staticWEPKeyLength}" Binding="{Binding _staticWEPKeyLength}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _staticWEPKey1}" Binding="{Binding _staticWEPKey1}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _staticWEPKey2}" Binding="{Binding _staticWEPKey2}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _staticWEPKey3}" Binding="{Binding _staticWEPKey3}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _staticWEPKey4}" Binding="{Binding _staticWEPKey4}"></DataGridTextColumn>
          <DataGridTextColumn Visibility="{Binding _wpaPersonalKeyAC}" Binding="{Binding _wpaPersonalKeyAC}"></DataGridTextColumn>
       </DataGrid.Columns>
    </DataGrid>
    

    C# code is :

    var ssid = new SSIDPropertyClass();
    
    ssid._networkID = SSID.Count + 1;
    ssid._ssid = EnteredSSIDAC;
    ssid._vlan = VlanSSID;
    
    if (ACSelectedSecurityType=="Static WEP")
    {
        ssid._authenticationMode = ACSelectedSecurityType;
        ssid._authentication = ACStaticWEPSelectedAuthentication;
    
        ssid._staticWEPKeyType = ACStaticWEPSelectedKeyType;
        ssid._staticWEPKeyLength = ACStaticWEPSelectedKeyLength;
    
        ssid._staticWEPKey1 = StaticWEPKey1;
        ssid._staticWEPKey2 = StaticWEPKey2;
        ssid._staticWEPKey3 = StaticWEPKey3;
        ssid._staticWEPKey4 = StaticWEPKey4;
    
        SSID.Add(ssid);
    }
    else if(ACSelectedSecurityType=="WPA/WPA2 Personal")
    {
        ssid._authenticationMode = ACSelectedSecurityType;
        ssid._wpaPersonalKeyAC = WpaACKey;
    
        SSID.Add(ssid);
    }
    

    I want that when if block is executed than it adds only that block columns in datagrid and same case for other else if block.Actually it is always displaying extra columns which I don't need For eg when else if is executed I want to display only that two which I have added in SSID collection but it is displaying if block columns too.So in a nutshell I want to make visibility of extra columns to false.Can anyone solve my issue as I need to submit it tomorrow.Any help would be greatly appreciable?