tags:

views:

3117

answers:

5

I have the following object in App.xaml

<Application.Resources>
        <ResourceDictionary>
            <GridView x:Key="myGridView" x:Shared="false">
                             <GridViewColumn Header="Created" DisplayMemberBinding="{Binding Path=Created}"/>

... more code ...

And I use this grid view in multiple places. Example:

<ListView x:Name="detailList"   View="{StaticResource myGridView}" ...>

In one of the usages (such as detailList above), I'd like to hide the Created column, possibly using XAML?

Any ideas?

A: 

I'd suggest using a custom property (or hijacking an existing one) on the parent and then using a custom style on the gridviewcolumnheader to reference that ancestor property. Like this:

<Window.Resources>
 <Style TargetType="{x:Type GridViewColumnHeader}">
        <Setter Property="Visibility" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=Tag}"/>
    </Style>
 <GridView x:Key="myGridView" x:Shared="false">                             
  <GridViewColumn Header="Created" DisplayMemberBinding="{Binding Path=Created}"/> 
 </GridView>
</Window.Resources>
<Grid x:Name="LayoutRoot">
    <StackPanel>
     <ListView x:Name="detailList"   View="{StaticResource myGridView}"/>
     <ListView x:Name="detailListHide" Tag="{x:Static Member=Visibility.Hidden}" View="{StaticResource myGridView}"/>
    </StackPanel>
</Grid>
Ben Reierson
I just realized that this only hides the column header, and that's probably not what you wanted to do. I can't find any way to hide the whole column with just xaml except just making a second gridview.
Ben Reierson
Setting a GridViewColumn's width to 0 will effectively hide it.
Enrico Campidoglio
I tried that, but it's not really gone then. You can still expand it with the mouse.
Ben Reierson
+3  A: 

You best bet is probably to create a custom control by inheriting from the GridView class, adding the required columns, and exposing a meaningful property to show/hide a particular column. Your custom GridView class could look like this:

using System;
using System.Windows.Controls;

namespace MyProject.CustomControls
{
    public class CustomGridView : GridView
    {
        private GridViewColumn _fixedColumn;
        private GridViewColumn _optionalColumn;

        public CustomGridView()
        {
            this._fixedColumn = new GridViewColumn() { Header = "Fixed Column" };
            this._optionalColumn = new GridViewColumn() { Header = "Optional Column" };

            this.Columns.Add(_fixedColumn);
            this.Columns.Add(_optionalColumn);
        }

        public bool ShowOptionalColumn
        {
            get { return _optionalColumn.Width > 0; }
            set
            {
                // When 'False' hides the entire column
                // otherwise its width will be set to 'Auto'
                _optionalColumn.Width = (!value) ? 0 : Double.NaN;
            }
        }

    }
}

Then you can simply set that property from XAML like in this example:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cc="clr-namespace:MyProject.CustomControls"
        Title="Window1"
        Height="300"
        Width="300">
    <StackPanel>
        <ListView>
            <ListView.View>
                <cc:CustomGridView ShowOptionalColumn="False" />
            </ListView.View>
        </ListView>

        <ListView>
            <ListView.View>
                <cc:CustomGridView ShowOptionalColumn="True" />
            </ListView.View>
        </ListView>
    </StackPanel>
</Window>

Optionally, you could make the 'CustomGridView.ShowOptionalColumn' a DependencyProperty to be able to use it as a binding target.

Enrico Campidoglio
+1  A: 

Taken from here

<ListView Grid.Column="1" Grid.Row="1"  Name="FicheList" >
            <ListView.Resources>
                <ResourceDictionary>
                    <Style x:Key="hiddenStyle" TargetType="GridViewColumnHeader">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </Style>
                </ResourceDictionary>
            </ListView.Resources>
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Code}" Header="Code" Width="0" HeaderContainerStyle="{StaticResource hiddenStyle}" />
                    <GridViewColumn DisplayMemberBinding="{Binding FicheTitle}" Header="Title" Width="100" />
                    <GridViewColumn DisplayMemberBinding="{Binding CategoryName}" Header="Category" Width="100" />
                    <GridViewColumn DisplayMemberBinding="{Binding UpdateDate}" Header="Update Date" Width="100" />

                </GridView>
            </ListView.View>
        </ListView>
Saber
Nice. Hides the header only, leaving cells visible.
modosansreves
+1  A: 

Actually, I find the easiest solution is via attached properties:

public class GridViewColumnVisibilityManager
{       
    static void UpdateListView(ListView lv)
    {
        GridView gridview = lv.View as GridView;
        if (gridview == null || gridview.Columns == null) return;
        List<GridViewColumn> toRemove = new List<GridViewColumn>();
        foreach (GridViewColumn gc in gridview.Columns)
        {
            if (GetIsVisible(gc) == false)
            {
                toRemove.Add(gc);
            }
        }
        foreach (GridViewColumn gc in toRemove)
        {
            gridview.Columns.Remove(gc);
        }
    }

    public static bool GetIsVisible(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsVisibleProperty);
    }

    public static void SetIsVisible(DependencyObject obj, bool value)
    {
        obj.SetValue(IsVisibleProperty, value);
    }

    public static readonly DependencyProperty IsVisibleProperty =
        DependencyProperty.RegisterAttached("IsVisible", typeof(bool), typeof(GridViewColumnVisibilityManager), new UIPropertyMetadata(true));


    public static bool GetEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(EnabledProperty);
    }

    public static void SetEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(EnabledProperty, value);
    }

    public static readonly DependencyProperty EnabledProperty =
        DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(GridViewColumnVisibilityManager), new UIPropertyMetadata(false,
            new PropertyChangedCallback(OnEnabledChanged)));

        private static void OnEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        ListView view = obj as ListView;
        if (view != null)
        {
            bool enabled = (bool)e.NewValue;
            if (enabled)
            {
                view.Loaded += (sender, e2) =>
                {
                    UpdateListView((ListView)sender);
                };
                view.TargetUpdated += (sender, e2) =>
                {
                    UpdateListView((ListView)sender);
                };
                view.DataContextChanged += (sender, e2) =>
                {
                    UpdateListView((ListView)sender);
                };
            }
        }
    }
}

Then, it can be used as so:

<ListView foo:GridViewColumnVisibilityManager.Enabled="True">
...
<GridViewColumn Header="Status" foo:GridViewColumnVisibilityManager.IsVisible="{Binding ShowStatusColumn}">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate> ...
Ben McMillan
my implementation expects the visibility of a column to be static for a load - if you expect this to change, however, you may need to fix UpdateListView() to do something else to hide and show the column (Width=0).
Ben McMillan
A: 

This is my code , it works very well in my project. if you don't like to add some external code.

    /// <summary>
    /// show/hide datagrid column
    /// </summary>
    /// <param name="datagrid"></param>
    /// <param name="header"></param>
    private void ToggleDataGridColumnsVisible()
    {
        if (IsNeedToShowHideColumn())
        {
            foreach (GridViewColumn column in ((GridView)(this.ListView1.View)).Columns)
            {
                GridViewColumnHeader header = column.Header as GridViewColumnHeader;
                if (header != null)
                {
                    string headerstring = header.Tag.ToString();

                    if (!IsAllWaysShowingHeader(headerstring ) )
                    {
                        if (IsShowingHeader())
                        {

                        }
                        else
                        {
                            //hide it
                            header.Template = null;
                            column.CellTemplate = null;
                            column.Width = 0;
                        }
                    }
                }

            }

        }
    }
ariso