web-dev-qa-db-fra.com

Visibilité de liaison pour DataGridColumn dans WPF

Comment masquer une colonne dans un fichier WPF DataGrid via une liaison?

C'est ce que j'ai fait:

<DataGridTextColumn Header="Column header"
                    Binding="{Binding ColumnValue}"
                    Width="100"
                    ElementStyle="{StaticResource DataGridRightAlign}"
                    Visibility="{Binding MyColumnVisibility}" />

Et voici ce que j'ai (à part la colonne encore visible):

Erreur System.Windows.Data: 2: impossible de trouver le FrameworkElement ou le FrameworkContentElement en vigueur pour l'élément cible. BindingExpression: Path = MyColumnVisibility; DataItem = null; l'élément cible est 'DataGridTextColumn' (HashCode = 1460142); propriété cible est 'Visibility' (type 'Visibility')

Je ne sais pas ce que gouverner signifie. Y a-t-il quelque part, quelque part dans ma fenêtre, M. le Président qui décide de ce qui fonctionne ou non? Ou devrais-je voter pour quelque chose?

En cherchant des solutions sur le Web, j'ai trouvé une douzaine de pages au titre prometteur, mais au contenu totalement inextricable ou non reproductible. Donc, cela semble être la première question sur le problème. Une idée?

59
ygoe

Tout d'abord DataGridTextColumn ou toute autre colonne de dataGrid prise en charge ne se trouve pas dans l'arborescence visuelle de DataGrid. Par conséquent, par défaut il n’hérite pas de DataContext de DataGrid. Mais cela fonctionne uniquement pour Binding DP et pas pour les autres DP sur DataGridColumn.

Comme ils ne se trouvent pas dans le même VisualTree, toute tentative d'obtenir DataContext à l'aide de RelativeSource ne fonctionnera pas aussi bien car DataGrid ne pourra pas traverser jusqu'à DataGrid.

Il y a deux façons d'y parvenir:


First en utilisant Freezable class - Freezable les objets peuvent hériter du DataContext même s’ils ne figurent pas dans l’arborescence visuelle ou logique. Nous pouvons donc en tirer parti pour notre usage.

Commencez par créer une classe héritant de Freezable et Data DP que nous pouvons utiliser pour lier en XAML:

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

Ajoutez maintenant une instance de celle-ci dans les ressources DataGrid afin qu'il puisse hériter du DataContext de DataGrid, puis se lier à son PDD de données:

    <DataGrid>
        <DataGrid.Resources>
            <local:BindingProxy x:Key="proxy" Data="{Binding}"/>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
                                                Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>

Second, vous pouvez faire référence à n’importe quel élément de l’UI en XAML en utilisant ElementName ou x:Reference. Mais ElementName ne fonctionne que dans le même arbre visuel, alors que x: Reference n'a pas cette contrainte.

Nous pouvons donc utiliser cela à notre avantage. Créez une valeur factice FrameworkElement dans XAML avec Visibility défini sur réduit. FrameworkElement héritera de DataContext de son conteneur parent qui peut être Window ou UserControl.

Et peut utiliser cela dans DataGrid:

    <FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Test"
                                Binding="{Binding Name}"
                                Visibility="{Binding DataContext.IsEnable,
                                          Source={x:Reference dummyElement}}"/>
        </DataGrid.Columns>
    </DataGrid>
141
Rohit Vats
<Window.Resources>
    <ResourceDictionary>
        <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}" />
    </ResourceDictionary>
</Window.Resources>

<!-- Necessary for binding to resolve: adds reference to ProxyElement to tree.-->
<ContentControl Content="{StaticResource ProxyElement}" Visibility="Collapsed" />
<mch:MCHDataGrid Height="350"
                  AutoGenerateColumns="False"
                  FlowDirection="LeftToRight"
                  ItemsSource="{Binding PayStructures}"
                  SelectedItem="{Binding SelectedItem}">
    <DataGrid.Columns>
         <DataGridTemplateColumn Width="70"
                                 Header="name"
                                 IsReadOnly="True"
                                 Visibility="{Binding DataContext.IsShowName,
                                 Source={StaticResource ProxyElement}}">
             <DataGridTemplateColumn.CellTemplate>
                 <DataTemplate>
                     <TextBlock Text="{Binding FieldName}" />
                 </DataTemplate>
             </DataGridTemplateColumn.CellTemplate>
         </DataGridTemplateColumn>                   
     </DataGrid.Columns>
</mch:MCHDataGrid>

Exemple de propriété liée dans le modèle de vue:

private Visibility _isShowName;

public Visibility IsShowName
{
    get { return _isShowName; }
    set
    {
        _isShowName = value;
        OnPropertyChanged();
    }
}
12
Meysam Chegini