我的 DataGrid
有一组默认列来显示,但我也想让用户选择/取消选择在他们的应用程序中显示的列。 在 WPF 中是否有相对简单的方法来实现这一点?
DataGrid
绑定到一个 DataTable
。
注意:如果上述功能太复杂,我可能只会使用一个简单的“默认列/所有列”通过 RadioButton
解决方案。
我的 DataGrid
有一组默认列来显示,但我也想让用户选择/取消选择在他们的应用程序中显示的列。 在 WPF 中是否有相对简单的方法来实现这一点?
DataGrid
绑定到一个 DataTable
。
注意:如果上述功能太复杂,我可能只会使用一个简单的“默认列/所有列”通过 RadioButton
解决方案。
将DataGrid.Columns
绑定到带有DataTemplate
的ItemsControl
,其中包含用于切换可见性的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>
[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
}
Visibility
属性到一个布尔标志上(通过复选框或其他机制设置),并使用BooleanToVisibilityConverter使得当标志未设置时,该列的可见性为Collapsed。我希望扩展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>