25

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?

Yael
  • 1,566
  • 3
  • 18
  • 25
Sapper
  • 285
  • 1
  • 4
  • 10
  • 1
    See this answer: http://stackoverflow.com/questions/7955318/bind-datagridtemplatecolumn-visibility – Rob Kent Mar 03 '15 at 14:23

4 Answers4

37

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;
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • 8
    I don't have a code behind option because I am using MVVM model I cannot directly access my dg as you said above! – Sapper Jul 16 '14 at 10:45
  • 3
    @Sapper You should make that clear in your question then, that you are using MVVM. – Rob Kent Mar 03 '15 at 14:14
  • During which event??? the columns in DataGrid are lot "loaded" yet on first appearance. The code above fails because there are no columns present in the collection. – jlo-gmail Jun 09 '18 at 17:06
5

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

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
  • 6
    [Binding Visibility for DataGridColumn in WPF](http://stackoverflow.com/a/22074985/1474994) – UndeadBob Aug 15 '16 at 14:16
  • @reasra Hi Reasra, would you like to elaborate on why you posted this link? Thanks. – Matas Vaitkevicius Aug 15 '16 at 14:20
  • 3
    I had been fighting with visibility on a `DataGridTextColumn` for a few days now, and it's not as simple as just setting visibility. For reasons that I don't fully understand, but are explained in the linked answer, the column isn't "visually connected" to the datagrid when binding values. When I stumbled on this post while looking for answers, I simply wanted to elaborate because I couldn't think of any reason one would set the visibility to a constant value (despite that it may work). – UndeadBob Aug 15 '16 at 17:18
  • @reasra One example 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 separate template and backing class. Or just for testing how would it look hidden. Or start as hidden and then make it visible in model with some trigger. – Matas Vaitkevicius Aug 15 '16 at 19:02
2

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

        DataGrid.Columns[IndexOfColumn].MaxWidth = 0;
2

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.

Geoff Scott
  • 897
  • 1
  • 10
  • 17
  • This results in an error because the DataGridTextColumn is not in the Visual Tree and does not have access to a DataContext. – andrew Dec 19 '19 at 03:31
  • The error: "Cannot find governing FrameworkElement or FrameworkContentElement for target element." – andrew Dec 19 '19 at 03:42
  • 2
    Apologies for missing the DataGridTextColumn is not in the Visual Tree. Have updated with corrected solution – Geoff Scott Jan 15 '20 at 02:02