我的DataGrid
有一组默认列显示,但我也想让用户选择/取消选择其应用程序中显示的列。在WPF中有相对简单的方法吗?
DataGrid
绑定到DataTable
。
注意:如果上述功能过于复杂,我可以通过RadioButton
解决方案使用简单的“默认列/所有列”。
答案 0 :(得分:6)
简短的回答是,将每列的Visibility
属性绑定到您能够设置的布尔标志(通过CheckBox或其他机制),并使用BooleanToVisibilityConverter来制作标志未设置时,列可见性折叠。
挖掘此similar question,特别是this answer!他的博客文章列出了我理想的解决方案。 :)
答案 1 :(得分:6)
将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>
之外无需代码:< / p>
TextBlock
注意:我有一个[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
}
,假设Column-Header是一个字符串,如果不是这样的话可能需要调整。
VisibilityConverter:
{{1}}
答案 2 :(得分:1)
我更喜欢扩展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>
现在,用户可以右键单击列标题以打开带有复选框的菜单: