51 votes

Lier la visibilité des colonnes d'une grille de données MVVM

.Net 3.5

Je sais que les colonnes n'héritent pas du datacontext et en lisant d'autres messages, je pensais que cela fonctionnerait :

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

Cependant, bien sûr, ce n'est pas le cas La fenêtre de sortie ne se plaint pas, il semble que la ressource a été trouvée mais que la propriété viewmodel n'a pas été appelée.

C'est la DG entière :

<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>

J'ai lu à peu près toutes les solutions à ce problème et rien ne fonctionne

109voto

WPF-it Points 10977

DataGridColumn ne font pas partie de l'arbre visuel, ils ne sont donc pas liés au contexte de données de l'élément DataGrid .

Pour qu'ils connecter utiliser ensemble l'approche de l'élément proxy comme ceci...

  1. Ajouter un proxy FrameworkElement dans le panneau de votre ancêtre Resources .
  2. L'héberger dans un endroit invisible ContentControl lié à son Content .
  3. Utilisez cette ProxyElement comme StaticResource pour la source du contexte de données dans votre liaison de visibilité.

    <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> 

En dehors de DataGridColumn L'approche ci-dessus fonctionne également très bien pour connecter DataContext à Popup et ContextMenu (c'est-à-dire tout élément qui n'est pas connecté à l'arbre visuel).

Utilisateurs de Silverlight

Malheureusement, la définition du contenu des contrôles de contenu avec n'importe quel élément du cadre n'est pas autorisée en Silverlight. La solution de contournement serait donc la suivante (il s'agit simplement d'un code d'orientation pour Silverlight) ...

  1. Changez la ressource de l'élément de cadre en quelque chose de léger comme un Textblock . (Silverlight ne permet pas de spécifier une ressource statique de type FrameworkElement type.)

    <StackPanel.Resources>
        <TextBlock x:Key="MyTextBlock" />
  2. Ecrivez une propriété attachée pour maintenir le bloc de texte contre le contrôle de contenu.

    <ContentControl Visibility="Collapsed" 
                    local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" />
  3. Dans le gestionnaire de l'événement de modification de la propriété de la dépendance jointe, définissez le contexte de données du contrôle de contenu sur celui du bloc de texte.

     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);
           }
     }

De cette façon, le bloc de texte peut ne pas être relié à l'arbre visuel mais probablement être conscient des changements de contexte des données.

J'espère que cela vous aidera.

-2voto

Felix C Points 806

Vous avez essayé :

Visibility="{Binding IsColumnNameVisible, Converter={StaticResource boolToVisConverter}}"

Avec cela, vous accédez à la IsColumnNameVisible de votre contexte de données.

Je suppose que vous avez créé le boolToVisConverter comme ceci :

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="boolToVisConverter" />
</Window.Resources>

Si tout cela ne fonctionne pas, jetez un coup d'oeil à L'espion des éléments . Je pense qu'avec elle, vous pouvez faire référence à votre contexte de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X