C# WPF DataGrid列可见性问题
我在WPF中使用DataGrid,而我在列可见性方面遇到了问题。我已将ItemSource分配给ObservableCollection,并在XAML中正确设置了所有绑定,一切正常。为了方便用户,我需要能够在UI上显示和隐藏列。我已经为C#文件中的列可见性设置了绑定,这些绑定可以正常显示和隐藏大多数列。但是,包含组合框的DataGridTemplateColumns重新显示为空。绑定仍然是正确设置的,因为一旦数据更改,它就会正确地推送到UI,并且再次可见。我还验证了当列被设置为隐藏时,底层数据没有被清除 这是我隐藏并显示带有组合框的列时得到的结果: 完整示例代码如下所示: XAML:C# WPF DataGrid列可见性问题,c#,wpf,xaml,datagrid,C#,Wpf,Xaml,Datagrid,我在WPF中使用DataGrid,而我在列可见性方面遇到了问题。我已将ItemSource分配给ObservableCollection,并在XAML中正确设置了所有绑定,一切正常。为了方便用户,我需要能够在UI上显示和隐藏列。我已经为C#文件中的列可见性设置了绑定,这些绑定可以正常显示和隐藏大多数列。但是,包含组合框的DataGridTemplateColumns重新显示为空。绑定仍然是正确设置的,因为一旦数据更改,它就会正确地推送到UI,并且再次可见。我还验证了当列被设置为隐藏时,底层数据没
C#:
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用系统组件模型;
使用System.Linq;
使用System.Runtime.CompilerServices;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
名称空间测试
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
ObservableCollection MyDevices=新的ObservableCollection();
GlobalVars GV=新的GlobalVars();
公共主窗口()
{
初始化组件();
DeviceDataGrid.ItemsSource=MyDevices;
添加(新的ExtendedDevice(){ModelName=“Model A”,IgmpVersion=eExtendedIgmpVersion.V2});
添加(新的ExtendedDevice(){ModelName=“Model B”,IgmpVersion=eExtendedIgmpVersion.V3});
添加(新的ExtendedDevice(){ModelName=“Model C”,IgmpVersion=eExtendedIgmpVersion.Unknown});
BindingOperations.SetBinding(this.DeviceDataGrid.Columns[0],DataGridColumn.VisibilityProperty,BindingHelper.CreateOneWayBindingWithConverter(GV,“ShowColumnModelName”,new BooleanToVisibleConverter(),null));
BindingOperations.SetBinding(this.MenuViewModelName、MenuItem.IsCheckedProperty、BindingHelper.CreateTwoWayBinding(GV,“ShowColumnModelName”);
BindingOperations.SetBinding(this.DeviceDataGrid.Columns[1],DataGridColumn.VisibilityProperty,BindingHelper.CreateOneWayBindingWithConverter(GV,“ShowColumnIgmp”,new BooleanToVisibleConverter(),null));
BindingOperations.SetBinding(this.MenuViewIgmp,MenuItem.IsCheckedProperty,BindingHelper.CreateTwoWayBinding(GV,“ShowColumnIgmp”);
}
}
公共枚举EExtendedImpVersion:int
{
V3=3,
V2=2,
未知=-1,
}
公共类扩展设备:发现的设备
{
私有eExtendedIgmpVersion _IgmpVersion=eExtendedIgmpVersion.Unknown;
公共eExtendedIgmpVersion IgmpVersion
{
获取{return\u IgmpVersion;}
设置{u IgmpVersion=value;RaisePropertyChanged();}
}
公共IEnumerable IGMPVersionValue
{
得到
{
返回Enum.GetValues(typeof(eExtendedIgmpVersion)).Cast();
}
}
公共扩展设备():基(){}
}
发现的公共类设备:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
私有字符串_ModelName;
公共字符串模型名
{
获取{return\u ModelName;}
设置{u ModelName=value;RaisePropertyChanged();}
}
受保护的虚拟void RaisePropertyChanged([CallerMemberName]字符串PropertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(PropertyName));
}
公共发现设备()
{
}
}
静态类BindingHelper
{
公共静态绑定CreateTowayBinding(对象源,字符串路径)
{
Binding myBinding=新绑定();
myBinding.Source=Source;
myBinding.Path=新属性路径(Path);
myBinding.Mode=BindingMode.TwoWay;
myBinding.UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged;
返回myBinding;
}
公共静态绑定CreateOneWayBindingWithConverter(对象源、字符串路径、IValueConverter转换器、对象转换器参数)
{
Binding myBinding=新绑定();
myBinding.Source=Source;
myBinding.Path=新属性路径(Path);
myBinding.Mode=BindingMode.OneWay;
myBinding.UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged;
myBinding.Converter=转换器;
myBinding.ConverterParameter=ConverterParameter;
返回myBinding;
}
}
公共类GlobalVars:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
private bool\u ShowColumnModelName=true;
公共布尔ShowColumnModelName
{
获取{return\u ShowColumnModelName;}
设置{u ShowColumnModelName=value;RaisePropertyChanged();}
}
private bool\u ShowColumnIgmp=true;
公共图书馆
{
获取{return\u ShowColumnIgmp;}
设置{u ShowColumnIgmp=value;RaisePropertyChanged();}
}
受保护的虚拟void RaisePropertyChanged([CallerMemberName]字符串PropertyName=null)
{
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="DeviceDataGrid" Margin="10,50,10,10" AutoGenerateColumns="False" CanUserReorderColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Model Name" IsReadOnly="true" Binding="{Binding ModelName}" Width="Auto">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="5,0"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTemplateColumn Header="IGMP" IsReadOnly="False" Width="Auto" SortMemberPath="IgmpVersion">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Margin="4" IsEnabled="True" ItemsSource="{Binding IgmpVersionValues}" SelectedItem="{Binding IgmpVersion}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Menu Height="25" VerticalAlignment="Top">
<MenuItem Header="View" Height="25">
<MenuItem x:Name="MenuViewModelName" Header="Model Name" HorizontalAlignment="Left" Width="175" IsCheckable="True" StaysOpenOnClick="True"/>
<MenuItem x:Name="MenuViewIgmp" Header="IGMP" HorizontalAlignment="Left" Width="175" IsCheckable="True" StaysOpenOnClick="True"/>
</MenuItem>
</Menu>
</Grid>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace Test
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<ExtendedDevice> MyDevices = new ObservableCollection<ExtendedDevice>();
GlobalVars GV = new GlobalVars();
public MainWindow()
{
InitializeComponent();
DeviceDataGrid.ItemsSource = MyDevices;
MyDevices.Add(new ExtendedDevice() { ModelName = "Model A", IgmpVersion = eExtendedIgmpVersion.V2 });
MyDevices.Add(new ExtendedDevice() { ModelName = "Model B", IgmpVersion = eExtendedIgmpVersion.V3 });
MyDevices.Add(new ExtendedDevice() { ModelName = "Model C", IgmpVersion = eExtendedIgmpVersion.Unknown });
BindingOperations.SetBinding(this.DeviceDataGrid.Columns[0], DataGridColumn.VisibilityProperty, BindingHelper.CreateOneWayBindingWithConverter(GV, "ShowColumnModelName", new BooleanToVisibleConverter(), null));
BindingOperations.SetBinding(this.MenuViewModelName, MenuItem.IsCheckedProperty, BindingHelper.CreateTwoWayBinding(GV, "ShowColumnModelName"));
BindingOperations.SetBinding(this.DeviceDataGrid.Columns[1], DataGridColumn.VisibilityProperty, BindingHelper.CreateOneWayBindingWithConverter(GV, "ShowColumnIgmp", new BooleanToVisibleConverter(), null));
BindingOperations.SetBinding(this.MenuViewIgmp, MenuItem.IsCheckedProperty, BindingHelper.CreateTwoWayBinding(GV, "ShowColumnIgmp"));
}
}
public enum eExtendedIgmpVersion : int
{
V3 = 3,
V2 = 2,
Unknown = -1,
}
public class ExtendedDevice : DiscoveredDevice
{
private eExtendedIgmpVersion _IgmpVersion = eExtendedIgmpVersion.Unknown;
public eExtendedIgmpVersion IgmpVersion
{
get { return _IgmpVersion; }
set { _IgmpVersion = value; RaisePropertyChanged(); }
}
public IEnumerable<eExtendedIgmpVersion> IgmpVersionValues
{
get
{
return Enum.GetValues(typeof(eExtendedIgmpVersion)).Cast<eExtendedIgmpVersion>();
}
}
public ExtendedDevice() : base() { }
}
public class DiscoveredDevice : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _ModelName;
public string ModelName
{
get { return _ModelName; }
set { _ModelName = value; RaisePropertyChanged(); }
}
protected virtual void RaisePropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public DiscoveredDevice()
{
}
}
static class BindingHelper
{
public static Binding CreateTwoWayBinding(Object Source, String Path)
{
Binding myBinding = new Binding();
myBinding.Source = Source;
myBinding.Path = new PropertyPath(Path);
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
return myBinding;
}
public static Binding CreateOneWayBindingWithConverter(Object Source, String Path, IValueConverter Converter, Object ConverterParameter)
{
Binding myBinding = new Binding();
myBinding.Source = Source;
myBinding.Path = new PropertyPath(Path);
myBinding.Mode = BindingMode.OneWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
myBinding.Converter = Converter;
myBinding.ConverterParameter = ConverterParameter;
return myBinding;
}
}
public class GlobalVars : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _ShowColumnModelName = true;
public bool ShowColumnModelName
{
get { return _ShowColumnModelName; }
set { _ShowColumnModelName = value; RaisePropertyChanged(); }
}
private bool _ShowColumnIgmp = true;
public bool ShowColumnIgmp
{
get { return _ShowColumnIgmp; }
set { _ShowColumnIgmp = value; RaisePropertyChanged(); }
}
protected virtual void RaisePropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
public class BooleanToVisibleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool? input = value as bool?;
return input == true ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
}