2016-11-16 8 views
3

DataGridのItemSourceであるObservableCollectionの内容に基づいて特定の列を非表示にするDataGridがあるウィンドウがあります。この質問に基づいて列の値に基づいてDataGrid列を非表示にする

Conditional element in xaml depending on the binding content

私はVisibilityConverterを書いた:ここ

public class StringLengthVisiblityConverter : IValueConverter 
{ 
    public StringLengthVisiblityConverter() { } 
    public Object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null || value.ToString().Length == 0) 
     { 
      return Visibility.Collapsed; 
     } 
     else 
     { 
      return Visibility.Visible; 
     } 
    } 

    public Object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

はXAMLです:

 <DataGrid.Resources> 
      <local:StringLengthVisiblityConverter x:Key="VisConverter"/> 
     </DataGrid.Resources> 
     <DataGrid.Columns> 

      <DataGridTextColumn Header="Switch Port" Binding="{Binding FCPort}"/> 
      <DataGridTextColumn Width="*" Header="WWPN" Binding="{Binding Path=WWPN}" 
         Visibility="{Binding Path=WWPN, Converter={StaticResource VisConverter}}"/> 
      <DataGridTextColumn Header="FCID" Binding="{Binding Path=FCID}" 
      Visibility="{Binding Path=FCID, Converter={StaticResource VisConverter}}"/> 

     </DataGrid.Columns> 
    </DataGrid> 

私はどこのクラスのインスタンスでコレクションをロードWWPNとFCIDは両方ともヌルです。私はそれらの列がデータグリッド内に隠されることを期待しましたが、まだ見えていました。私はVisbilityConverterにブレークポイントを追加し、デバッガを介してそれを実行しましたが、呼び出されるように見えません。

+1

すべての項目が空の文字列またはnullの場合は、完全な列を非表示にしますか?その後、アイテムにバインドして(パスを空にして)アイテムを繰り返し処理するMultiValueConverterを作成できます。 – WPFGermany

+1

これは、 'DataGridColumn'が' FrameworkElement'や 'FrameworkContentElement'ではなく' DependencyObject'から直接派生しているため、データコンテキストが継承されないからです。出力ウィンドウをチェックすると、そこに 'System.Windows.Data:Error:2'メッセージがあるはずです。 – Grx70

+0

[ここには良い記事があります](https://blogs.msdn.microsoft.com/jaimer/2008/11/22/forwarding-the-datagrids-datacontext-to-its-columns/)の説明と回避策があります正確な問題。 – Grx70

答えて

1

DataGridTextColumnの各値を確認し、それに応じてColumn.Visibilityを設定する必要があります。 DataGridから派生したすべてのロジックをラップします。

あなたは、もはやそれが自動的に起こるようにXAMLで Column.Visibilityを設定する必要が MyDataGridを使用し
public class MyDataGrid : DataGrid 
{ 
    private void ValidateColumnVisibility() 
    { 
     if (Items.Count == 0 || Items[0] == CollectionView.NewItemPlaceholder) return; 
     var itemClass = Items[0].GetType(); 
     foreach (var column in Columns) 
     { 
      if (column.GetType() == typeof(DataGridTextColumn)) 
      { 
       // find the property that this column is bound to 
       DataGridBoundColumn boundColumn = column as DataGridBoundColumn; 
       Binding binding = boundColumn.Binding as Binding; 
       string boundPropertyName = binding.Path.Path; 
       var prop = itemClass.GetProperty(boundPropertyName); 

       // Validating Column.Visibility when first value is null 
       // when all values are null -> Visibility.Collapsed 
       // bound value not a string -> Visibility.Visible 
       // all bound strings empty -> Visibility.Collapsed 
       if (prop.GetValue(Items[0]) == null) 
       { 
        column.Visibility = Visibility.Collapsed; 
        foreach (var item in Items) 
        { 
         if (item != CollectionView.NewItemPlaceholder) 
         { 
          if (prop.GetValue(item) != null) 
          { 
           if (prop.GetValue(item).GetType() != typeof(String)) 
            column.Visibility = Visibility.Visible; 
           else if (String.IsNullOrEmpty(prop.GetValue(item) as String) == false) 
            column.Visibility = Visibility.Visible; 
          } 
         } 
        } 
       } 

       // First value not null and all bound strings empty -> Visibility.Collapsed 
       else if (prop.GetValue(Items[0]).GetType() == typeof(String)) 
       { 
        column.Visibility = Visibility.Collapsed; 
        foreach (var item in Items) 
        { 
         if (item != CollectionView.NewItemPlaceholder) 
         { 
          if (String.IsNullOrEmpty(prop.GetValue(item) as String) == false) 
           column.Visibility = Visibility.Visible; 
         } 
        } 
       } 
      } 
     } 
    } 

    protected override void OnItemsSourceChanged(
     IEnumerable oldValue, IEnumerable newValue) 
    { 
     base.OnItemsSourceChanged(oldValue, newValue); 
     ValidateColumnVisibility(); 
    } 

    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) 
    { 
     base.OnItemsChanged(e); 
     ValidateColumnVisibility(); 
    } 
} 

+0

それは非常にきれいで、私はそうするだろうと思う。 XAMLもクリーンアップされます。 –

関連する問題