Разрешить пользователю выбирать столбцы для отображения в WPF DataGrid - PullRequest
3 голосов
/ 12 января 2011

My DataGrid имеет набор столбцов по умолчанию для отображения, но я также хотел бы позволить пользователю выбирать / отменять выбор столбцов, отображаемых в их приложении. Есть ли относительно простой способ сделать это в WPF?

DataGrid привязан к DataTable.

Примечание: я могу просто пойти с простым решением "Столбцы по умолчанию / Все столбцы" через RadioButton решение, если вышеуказанная функция слишком сложна.

Ответы [ 3 ]

6 голосов
/ 12 января 2011

Свяжите DataGrid.Columns с ItemsControl с DataTemplate, который содержит CheckBox для переключения видимости, код не требуется, кроме VisbilityToBoolConverter:

<Window
    ...
    DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}" Loaded="Window_Loaded">
    <Window.Resources>
        <local:VisibilityToBoolConverter x:Key="VisibilityToBoolConv"/>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <DataGrid ItemsSource="{Binding Data}" Name="DGrid"/>
        <ItemsControl ItemsSource="{Binding ElementName=DGrid, Path=Columns}" Grid.IsSharedSizeScope="True" Margin="5">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition SharedSizeGroup="A"/>
                            <ColumnDefinition SharedSizeGroup="B"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Header}" Margin="5"/>
                        <CheckBox Grid.Column="1"  IsChecked="{Binding Visibility, Converter={StaticResource VisibilityToBoolConv}}" Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</Window>

Примечание:У меня есть TextBlock, который предполагает, что заголовок столбца является строкой, возможно, потребуется изменить его, если это не так.


VisibilityConverter:

[ValueConversion(typeof(Visibility), typeof(bool))]
public class VisibilityToBoolConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Visibility vis = (Visibility)value;
        switch (vis)
        {
            case Visibility.Collapsed:
                return false;
            case Visibility.Hidden:
                return false;
            case Visibility.Visible:
                return true;
        }
        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if ((bool)value) return Visibility.Visible;
        else return Visibility.Collapsed;
    }

    #endregion
}
6 голосов
/ 12 января 2011

Краткий ответ: свяжите свойство Visibility каждого столбца с логическим флагом, который вы можете установить (через CheckBox или другой механизм), и используйте BooleanToVisibilityConverter , чтобы сделатьвидимость столбца Свернулся , когда флаг не установлен.

Копайте этот аналогичный вопрос , и особенно этот ответ !Его сообщение в блоге перечисляет то, что было бы моим идеальным решением.:)

0 голосов
/ 04 июля 2019

Я предпочитаю расширить класс DataGrid и добавить эту функциональность.

public class DataGridEx : DataGrid
{
    public DataGridEx() : base()
    {
        // Create event for right click on headers
        var style = new Style { TargetType = typeof(DataGridColumnHeader) };
        var eventSetter = new EventSetter(MouseRightButtonDownEvent, new MouseButtonEventHandler(HeaderClick));
        style.Setters.Add(eventSetter);
        ColumnHeaderStyle = style;
    }

    private void HeaderClick(object sender, MouseButtonEventArgs e)
    {
        ContextMenu menu = new ContextMenu();
        // Fill context menu with column names and checkboxes
        var visibleColumns = this.Columns.Where(c => c.Visibility == Visibility.Visible).Count();
        foreach (var column in this.Columns)
        {
            var menuItem = new MenuItem
            {
                Header = column.Header.ToString(),
                IsChecked = column.Visibility == Visibility.Visible,
                IsCheckable = true,
                // Don't allow user to hide all columns
                IsEnabled = visibleColumns > 1 || column.Visibility != Visibility.Visible
            };
            // Bind events
            menuItem.Checked += (object a, RoutedEventArgs ea)
                => column.Visibility = Visibility.Visible;
            menuItem.Unchecked += (object b, RoutedEventArgs eb)
                => column.Visibility = Visibility.Collapsed;
            menu.Items.Add(menuItem);
        }
        // Open it
        menu.IsOpen = true;
    }
}

Теперь вы можете использовать этот элемент управления вместо оригинального DataGrid:

<dg:DataGridEx ItemsSource="{Binding OfflineData, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False">
    <dg:DataGridEx.Columns>
        <DataGridTextColumn Binding="{Binding PortID}" Header="ID" Width="50" Visibility="Collapsed"/>
        <DataGridTextColumn Binding="{Binding SwitchIP}" Header="Switch IP" Width="100" Visibility="Visible"/>
        <DataGridTextColumn Binding="{Binding Port}" Header="Port" Width="50" Visibility="Visible"/>
    </dg:DataGridEx.Columns>
</dg:DataGridEx>

Теперь пользователь может щелкнуть правой кнопкой мыши заголовок столбца, чтобы открыть меню с флажками:

Now user can right-click on column header to open menu with checkboxes

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...