2011-10-10 5 views
45

に.NET 3.5バインドデータグリッド列の可視性のMVVM

私は列がDataContextのを継承し、私はこれが働くだろうと思ったの他の記事を読むことでないことを知っている:

Visibility="{Binding RelativeSource={x:Static RelativeSource.Self}, 
        Path=(FrameworkElement.DataContext).IsColumnNameVisible, 
        Converter={StaticResource boolToVisConverter}}" 

しかし、もちろんそれはdoesnのt .. 出力ウィンドウは表示されません。リソースが見つかりましたが、viewmodelプロパティが呼び出されたようです。

これは全体のDGである:

<tk:DataGrid           
      VirtualizingStackPanel.IsVirtualizing="False"           
      Grid.Column="0" 
      AlternationCount="2" 
      AreRowDetailsFrozen="True" 
      AutoGenerateColumns="False" 
      Background="Transparent" 
      BorderThickness="0" 
      CanUserAddRows="False" 
      CanUserReorderColumns="True" 
      CanUserResizeRows="False" 
      GridLinesVisibility="None" 
      ItemsSource="{Binding Employees}" 
      SelectionMode="Single" 
      ColumnHeaderStyle="{StaticResource columnHeaderStyle}" 
      RowHeaderStyle="{StaticResource rowHeaderStyle}" 
      CellStyle="{StaticResource cellStyle}" 
      RowStyle="{StaticResource rowStyle}" 
      ContextMenu="{StaticResource columnHeaderContextMenu}"> 
    <tk:DataGrid.Resources> 
     <ContextMenu x:Key="columnHeaderContextMenu" ItemsSource="{Binding ColumnHeaderContextMenuItems}" /> 
     <Style TargetType="{x:Type ScrollBar}"> 
      <Setter Property="Background" Value="Transparent"/> 
     </Style>          
     <Style TargetType="{x:Type tk:DataGridColumnHeader}"> 
      <Setter Property="Background" Value="Transparent"/> 
     </Style> 
    </tk:DataGrid.Resources> 
    <tk:DataGrid.Triggers> 
     <EventTrigger RoutedEvent="tk:DataGridRow.MouseDoubleClick"> 
      <EventTrigger.Actions> 
       <BeginStoryboard Storyboard="{StaticResource showDetailGrid}"/> 
      </EventTrigger.Actions> 
     </EventTrigger> 
    </tk:DataGrid.Triggers> 
    <tk:DataGrid.Columns> 
     <tk:DataGridTextColumn IsReadOnly="True" Header="test" Binding="{Binding Name, Mode=OneWay}" Visibility="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(FrameworkElement.DataContext).IsColumnNameVisible, Converter={StaticResource boolToVisConverter}}" /> 
    </tk:DataGrid.Columns> 
</tk:DataGrid> 

私はかなりこの問題を一つ一つ解決策を読んでいると、何も動作...それらが接続されていないので、

+0

ご質問が少し不明な場合は、バインドされたViewModelプロパティに応じて、データ列を表示または非表示にするだけですか? – ChrisBD

+0

ContextMenuを ''で変更しました。ウィンドウのDataContextに到達できないのは不思議ではありません。 –

+0

@ ChrisBD:そうですね。 VM propはdatacontextを介して設定されます。 – jrb

答えて

95

DataGridColumn sがビジュアルツリーの一部ではありませんDataGridのデータコンテキストに変換します。 に彼らのために

一緒を接続するには、このようなプロキシ要素のアプローチを使用して...

  1. は、あなたの先祖パネルのResourcesでプロキシFrameworkElementを追加します。
  2. Contentにバインドされた不可視のContentControlにホストします。
  3. ProxyElementStaticResourceとして、可視性バインディングのデータコンテキストソースに使用します。

    <StackPanel> 
        <StackPanel.Resources> 
         <local:BooleanToVisibilityConverter 
           x:Key="BooleanToVisibilityConverter" /> 
    
         <FrameworkElement x:Key="ProxyElement" 
             DataContext="{Binding}"/> 
        </StackPanel.Resources> 
        <ContentControl Visibility="Collapsed" 
           Content="{StaticResource ProxyElement}"/> 
        <DataGrid AutoGenerateColumns="False"> 
         <DataGrid.Columns> 
          <DataGridTextColumn 
            Visibility="{Binding DataContext.IsTextColumnVisibile, 
                 Source={StaticResource ProxyElement}, 
                 Converter={StaticResource 
                  BooleanToVisibilityConverter}}" 
            Binding="{Binding Text}"/> 
         </DataGrid.Columns> 
        </DataGrid> 
    </StackPanel> 
    

以外DataGridColumnから、上記のアプローチは、DataContextPopup秒とContextMenu S(ビジュアルツリーに接続されていない、すなわち任意の要素)を接続する素晴らしい作品。

Silverlightのユーザー

は、悲しいことにSilverlightで許可されていない任意のフレームワーク要素とコンテンツコントロールの内容を設定します。そこで、この問題を回避するには、

  1. 変更Textblockのような軽量なものに枠組み要素リソース...(これはSilverlightのためだけの指導のコードです)になります。 (SilverlightはFrameworkElementタイプの静的リソースを指定することはできません。)

    <StackPanel.Resources> 
        <TextBlock x:Key="MyTextBlock" /> 
    
  2. コンテンツ制御に対するテキストブロックを保持するために、添付プロパティを書きます。添付依存プロパティ変更イベントハンドラで

    <ContentControl Visibility="Collapsed" 
           local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" /> 
    
  3. 、バインドにテキストブロックのコンテンツへのコントロールのデータコンテキストを設定します。テキストブロックは、ビジュアルツリーに接続されていないが、はおそらくデータコンテキストが変更に気付くであろう

ので、この方法。

これが役に立ちます。

+0

選択を解除して再選択すると例外が発生します:指定された要素はすでに別の要素の論理的な子です。最初に切断します。なぜあなたは知っていますか? – jrb

+0

あなたの 'ContextMenu'であるかもしれません...それは1つの親にのみ付けることができます。 –

+0

ContextMenuをDGColumnHeader CMではなくDataGrid CMに変更しましたが、それは役に立ちませんでした。もし問題があれば、私は複数の列でこれを使用します。 – jrb