WPF: How to hide GridViewColumn using XAML?

后端 未结 10 605
北海茫月
北海茫月 2020-12-05 09:59

I have the following object in App.xaml


        
            

        
相关标签:
10条回答
  • 2020-12-05 10:33
    <GridViewColumn Width="{Binding Tag, RelativeSource={RelativeSource AncestorType=ListView}, Converter={converters:BooleanToWidthConverter}, ConverterParameter=100}">
                                <GridViewColumn.HeaderContainerStyle>
                                    <Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource ColumnHeaderStyle}">
                                        <Setter Property="IsEnabled" Value="False"/>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource AncestorType=ListView}}" Value="true">
                                                <Setter Property="IsEnabled" Value="True"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </GridViewColumn.HeaderContainerStyle>
                                <GridViewColumn.Header>
                                    <StackPanel Tag="columnHeader" Orientation="Horizontal">
                                    </StackPanel>
                                </GridViewColumn.Header>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <ContentControl>
                                            <TextBlock Text="test" />
                                        </ContentControl>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
    

    class BooleanToWidthConverter :IValueConverter {

        public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool b)
            {
                return b ? parameter : 0;
            }
            return 0;
        }
    
        public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
    

    Unfortunately, there is no "IsVisible" Property in GridViewColumn But, I have a solution can solve this problem by simple and complete way:

    1. Setting width to 0. Many Dev just stop at this step, because it seems to have been hidden but not. We still make it extendible hence bringing it back on the UI by resize column, so we need to do more step 2.
    2. Disable resize GridViewColumn by set GridViewColumnHeader IsEnabled = false.

    Code sample above:

    0 讨论(0)
  • 2020-12-05 10:35

    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>
    
    0 讨论(0)
  • 2020-12-05 10:41

    Based on Ben McMillan's answer, but supports dynamic changing of visible property. I've simplified his solution further by removing the IsEnabled property.

    public class GridViewColumnVisibilityManager
    {
        static Dictionary<GridViewColumn, double> originalColumnWidths = new Dictionary<GridViewColumn, double>();
    
        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, OnIsVisibleChanged));
    
        private static void OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            GridViewColumn gc = d as GridViewColumn;
            if (gc == null)
                return;
    
            if (GetIsVisible(gc) == false)
            {
                originalColumnWidths[gc] = gc.Width;
                gc.Width = 0;
            }
            else
            {
                if (gc.Width == 0)
                    gc.Width = originalColumnWidths[gc];
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 10:42

    I have a much simpler solution than using an Attached Behavior.

    All you have to do is bind the Width Property of the GridViewColumn to a boolean on your ViewModel. Then create a simple Converter like BooleanToWidthConverter that takes a boolean and returns a double, zero if its false, x width if its true.

    I hope this helps and makes your life easier.

    XAML:

    <GridViewColumn x:Name="MyHiddenGridViewColumn"
                    Width={Binding Path=IsColumnVisibleProperty, Converter={StaticResource BooleanToWidthConverter}}">
       <!-- GridViewColumn.HeaderTemplate etc. goes here. -->
    </GridViewColumn>
    

    Converter:

    public class BooleanToWidthConverter : IValueConverter
        {
            private const double Column_Width = 40.0;
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value != null && value != DependencyProperty.UnsetValue)
                {
                    bool isVisible = (bool) value;
    
                    return isVisible ? Column_Width : 0;
                }
                return Column_Width;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
    0 讨论(0)
  • 2020-12-05 10:44

    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>
    
    0 讨论(0)
  • 2020-12-05 10:46

    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> ...
    
    0 讨论(0)
提交回复
热议问题