web-dev-qa-db-ja.com

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

.Net 3.5

私は、列がデータコンテキストを継承しないことを知っており、他の投稿を読むことでこれがうまくいくと思いました:

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

しかし、もちろんそうではありません。出力ウィンドウは文句を言わず、私が見つけたリソースであるように見えますが、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>

私はこの問題のほとんどすべての解決策を読みましたが、何も機能しません。

49
jrb

DataGridColumnsはビジュアルツリーの一部ではないため、DataGridのデータコンテキストに接続されていません。

彼らのためにconnect一緒にこのようなプロキシ要素アプローチを使用してください...

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

    <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とは別に、上記のアプローチはDataContextPopupsおよびContextMenus(つまり、ビジュアルツリーに接続されていない要素)に接続するのにも最適です。 。

Silverlightユーザー

悲しいことに、フレームワーク要素でコンテンツコントロールのコンテンツを設定することは、Silverlightでは許可されていません。回避策は次のようになります(これは単にsilverlightのガイダンスコードです)...

  1. フレームワーク要素リソースをTextblockなどの軽量のものに変更します。 (Silverlightでは、FrameworkElementタイプの静的リソースを指定できません。)

    <StackPanel.Resources>
        <TextBlock x:Key="MyTextBlock" />
    
  2. コンテンツコントロールに対してテキストブロックを保持する添付プロパティを記述します。

    <ContentControl Visibility="Collapsed" 
                    local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" />
    
  3. 添付された依存関係プロパティ変更イベントハンドラで、コンテンツコントロールのデータコンテキストをテキストブロックにバインドするように設定します。

     private static void OnProxyElementPropertyChanged(
         DependencyObject depObj, DependencyPropertyChangedEventArgs e)
     {
           if (depObj is ContentControl && e.NewValue is TextBlock)
           {
               var binding = new Binding("DataContext");
               binding.Source = depObj;
               binding.Mode = OneWay;
               BindingOperations.SetBinding(
                   (TextBlock)e.NewValue, TextBlock.DataContextProperty, binding);
           }
     }
    

そのため、この方法では、テキストブロックはビジュアルツリーに接続されていない可能性がありますが、おそらくデータコンテキストの変更を認識します。

お役に立てれば。

102
WPF-it