如何使用MVVM自动隐藏WPF中的DataGrid列?

25

使用MVVM(无代码后台),我想在选择时隐藏我的DataGrid列,我有以下代码:

<DataGrid ItemsSource="{Binding SSID}" Grid.Row="1"  Margin="10,10,0,0" Height="200" Width="500" Grid.ColumnSpan="2" Name="dg" HorizontalAlignment="Left" AutoGenerateColumns="False">
    <DataGrid.Columns>
      <DataGridTextColumn Header="Network ID" Binding="{Binding _networkID}"></DataGridTextColumn>
      <DataGridTextColumn Header="SSID" Binding="{Binding _ssid}"></DataGridTextColumn>
      <DataGridTextColumn Header="VLAN" Binding="{Binding _vlan}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _authenticationMode}" Binding="{Binding _authenticationMode}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _authentication}" Binding="{Binding _authentication}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _staticWEPKeyType}" Binding="{Binding _staticWEPKeyType}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _staticWEPKeyLength}" Binding="{Binding _staticWEPKeyLength}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _staticWEPKey1}" Binding="{Binding _staticWEPKey1}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _staticWEPKey2}" Binding="{Binding _staticWEPKey2}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _staticWEPKey3}" Binding="{Binding _staticWEPKey3}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _staticWEPKey4}" Binding="{Binding _staticWEPKey4}"></DataGridTextColumn>
      <DataGridTextColumn Visibility="{Binding _wpaPersonalKeyAC}" Binding="{Binding _wpaPersonalKeyAC}"></DataGridTextColumn>
   </DataGrid.Columns>
</DataGrid>

C# 代码是:

var ssid = new SSIDPropertyClass();

ssid._networkID = SSID.Count + 1;
ssid._ssid = EnteredSSIDAC;
ssid._vlan = VlanSSID;

if (ACSelectedSecurityType=="Static WEP")
{
    ssid._authenticationMode = ACSelectedSecurityType;
    ssid._authentication = ACStaticWEPSelectedAuthentication;

    ssid._staticWEPKeyType = ACStaticWEPSelectedKeyType;
    ssid._staticWEPKeyLength = ACStaticWEPSelectedKeyLength;

    ssid._staticWEPKey1 = StaticWEPKey1;
    ssid._staticWEPKey2 = StaticWEPKey2;
    ssid._staticWEPKey3 = StaticWEPKey3;
    ssid._staticWEPKey4 = StaticWEPKey4;

    SSID.Add(ssid);
}
else if(ACSelectedSecurityType=="WPA/WPA2 Personal")
{
    ssid._authenticationMode = ACSelectedSecurityType;
    ssid._wpaPersonalKeyAC = WpaACKey;

    SSID.Add(ssid);
}

我希望当执行if块时,仅将该块列添加到数据网格中,并且对于其他的else if块也是同样的情况。现在它总是显示我不需要的额外列。例如,当执行else if时,我只想显示我已经添加到SSID集合中的两个列,但它也显示了if块列。因此,简而言之,我希望将额外列的可见性设置为false。请问有谁能解决我的问题?因为我需要在明天提交。非常感谢任何帮助!


1
请参考此答案:https://dev59.com/JlzUa4cB1Zd3GeqP6MG1 - Rob Kent
4个回答

37

如果您想隐藏列,需要像这样指定属性Visibility

YourDataGrid.Columns[IndexOftheColumn].Visibility = Visibility.Collapsed;

如果您想隐藏第一列,即“网络ID”,

dg.Columns[0].Visibility = Visibility.Collapsed;

8
我无法使用代码后台选项,因为我正在使用MVVM模型,不能像你上面说的那样直接访问我的dg! - Sapper
3
@Sapper 你应该在问题中明确说明你正在使用MVVM。 - Rob Kent
在哪个事件中,DataGrid中的列在第一次出现时尚未“加载”。上面的代码失败是因为集合中没有列存在。 - jlo-gmail

5
对于那些希望在XAML中隐藏它的人,
它看起来应该像这样:
<DataGridTextColumn Visibility="Collapsed" Header="Merchant Reference" Binding="{Binding MerchantReference}" Width="200" />

使用XAML而不是代码的原因之一是当您有一个模板具有额外的列而某些情况下不适用时,但您懒得制作单独的模板和支持类。
另一个原因是仅用于测试如何隐藏它的外观。
第三种是在模型中以某些触发器开始隐藏,然后使其可见。


6
在WPF中对于DataGridColumn实现绑定可见性,可以使用以下两种方法:1) 创建一个布尔类型的属性,用于标识该列是否可见,并在XAML中使用绑定来设置Visibility属性;2)使用IValueConverter接口实现自定义转换器,将绑定的值转换为Visibility属性。 - UndeadBob
@reasra 嗨Reasra,你是否愿意详细说明为什么你发布了这个链接?谢谢。 - Matas Vaitkevicius
3
我已经花了几天时间在DataGridTextColumn上解决可见性问题,但它并不像简单的设置可见性那样容易。我不完全理解其中的原因,但这篇文章中解释了一些,当绑定值时,该列与数据网格没有"视觉连接"。当我在寻找答案时偶然发现了这篇文章,我只是想进一步说明,因为我无法想出任何原因将可见性设置为常量值(尽管可能有效)。 - UndeadBob
一个例子是当你有一个模板,其中有一列不适用于某些情况,但你很懒,不想制作单独的模板和支持类。或者只是为了测试隐藏后的效果。或者在模型中以某种触发器将其从隐藏状态变为可见状态。 - Matas Vaitkevicius

3

MVVM中,通常通过ValueConverter来处理此类情况。

public sealed class BoolToVisibilityConverter : IValueConverter
{
   public Visibility TrueValue { get; set; }
   public Visibility FalseValue { get; set; }

   public BoolToVisibilityConverter()
   {
      // Set defaults
      this.TrueValue = Visibility.Visible;
      this.FalseValue = Visibility.Collapsed;
   }

   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
       bool flag = false;
       if (value is bool)
       {
          flag = (bool)value;
       }
       else if (value is bool?)
       {
          bool? nullable = (bool?)value;
          flag = nullable.HasValue ? nullable.Value : false;
      }
      return flag ? this.TrueValue : this.FalseValue;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
      if (object.Equals(value, this.TrueValue))
          return true;
      if (object.Equals(value, this.FalseValue))
        return false;
      return null;
  }
}

由于DataGridTextColumn或其他支持的DataGrid列不在DataGrid的可视树中(请参见WPF中DataGridColumn的可见性绑定),因此需要添加一个绑定代理。

public class BindingProxy : Freezable
{
#region Overrides of Freezable

protected override Freezable CreateInstanceCore()
{
    return new BindingProxy();
}

#endregion

public object Data
{
    get { return (object)GetValue(DataProperty); }
    set { SetValue(DataProperty, value); }
}

public static readonly DependencyProperty DataProperty =
    DependencyProperty.Register("Data", typeof(object),
                                 typeof(BindingProxy));

在资源部分添加

<ResourceDictionary>
   <namespace:BoolToVisibilityConverter x:Key="BoolToCollapsed" TrueValue="Visible" FalseValue="Collapsed" />
   <namespace:BindingProxy x:Key="Proxy" Data="{Binding}"/>
</ResourceDictionary>

在你的数据网格上
 <DataGrid ItemsSource="{Binding Items}" >
    <DataGrid.Columns>
      <DataGridTextColumn Visibility="{Binding Data.ShowThisColumnFlag, Source={StaticResource Proxy}, Converter={StaticResource BoolToCollapsed}}" Binding="{Binding PropertyOne}" />

      <DataGridTextColumn Visibility="{Binding Data.ShowAnotherColumnFlag, Source={StaticResource Proxy}, Converter={StaticResource BoolToCollapsed}}" Binding="{Binding PropertyTwo}"/>
    </DataGrid.Columns>
 </DataGrid>

你应该根据需要设置你的模式。感谢Rohit Vats发布了BindingProxy文章。

因为DataGridTextColumn不在可视树中,也无法访问DataContext,所以会导致错误。 - andrew
错误:"无法找到目标元素的主控 FrameworkElement 或 FrameworkContentElement。" - andrew
2
抱歉错过了DataGridTextColumn不在Visual Tree中的问题。已更新并提供了正确的解决方案。 - Geoff Scott

2

您不必隐藏列,只需将其MaxWidth属性设置为零即可使其不出现。

        DataGrid.Columns[IndexOfColumn].MaxWidth = 0;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接