it-swarm.com.de

Ausblenden von wpf-Datagrid-Spalten in Abhängigkeit von einer Eigenschaft

Ich habe das folgende WPF-Beispielprogramm:

Xaml:

<Window x:Class="AncestorArie.MainWindow"
        xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVis" />
    </Window.Resources>
    <Grid>
        <DataGrid AutoGenerateColumns="False" Name="Blumen" 
                  ItemsSource="{Binding Leaves}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Color}" 
                                    Header="Farbe" Width="160" />
                <DataGridTextColumn Binding="{Binding Size}" 
                                    Header="Größe" Width="60"
                                    Visibility="{Binding Path=DataContext.Flag, 
                                                RelativeSource={RelativeSource Findancestor, 
                                                AncestorType={x:Type Window}}, 
                                                Converter={StaticResource BoolToVis}}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Code dahinter:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Flowers rose = new Flowers();
        rose.Leaves = new ObservableCollection<Leaf>();

        rose.Flag = false;

        Leaf L1 = new Leaf();
        L1.Color = "rot";
        L1.Size = 3;
        rose.Leaves.Add(L1);

        Leaf L2 = new Leaf();
        L2.Color = "gelb";
        L2.Size = 2;
        rose.Leaves.Add(L2);

        this.DataContext = rose;            
    }
}

Und die Modellklassen sind:

public class Leaf
{
    public string Color { get; set; }
    public int Size { get; set; }
}

public class Flowers
{
    public bool Flag { get; set; }
    public ObservableCollection<Leaf> Leaves { get; set; }
}

Wie Sie sehen, möchte ich die zweite Datagrid-Spalte ausblenden, wenn die Eigenschaft Flag auf false festgelegt ist. Aber es geht nicht. Im Visual Studio-Ausgabefenster wird der folgende Bindungsfehler angezeigt:

System.Windows.Data Fehler: 4: Die Quelle für die Bindung mit dem Verweis 'RelativeSource FindAncestor, AncestorType =' System.Windows.Window ', AncestorLevel =' 1 '' kann nicht gefunden werden. BindingExpression: Path = DataContext.Flag; DataItem = null; Zielelement ist 'DataGridTextColumn' (HashCode = 44856655); Zieleigenschaft ist 'Visibility' (Typ 'Visibility')

Was ist in meinem Code bezüglich des Attributs Visibility falsch?

18
Hulda

Eine Spalte in einem Datagrid ist ein abstraktes Objekt, das nicht in der visuellen Struktur angezeigt wird. Daher können Sie RelativeSource- binding nicht verwenden. ElementName funktioniert auch nicht, da es kein maßgebliches FrameworkContentElement findet, sodass Sie sich in einer Art Bind befinden.

Eine Möglichkeit, die funktioniert, ist über Source und x:Reference . Dazu müssen Sie Ihr Fenster benennen und die Spalte in ihre Ressourcen verschieben, um einen zyklischen Abhängigkeitsfehler zu vermeiden:

<Window Name="_window" ...>
    <Window.Resources>
        <DataGridTextColumn x:Key="ThatPeskyColumn"
                            Binding="{Binding Size}"
                            Visibility="{Binding DataContext.Flag, Source={x:Reference _window}, Converter={StaticResource BoolToVis}}"/>
    </Window.Resources>
    <!-- ... -->
        <DataGrid AutoGenerateColumns="False" Name="Blumen" 
                  ItemsSource="{Binding Leaves}">
            <DataGrid.Columns>
                <StaticResource ResourceKey="ThatPeskyColumn"/>
                <!-- ... -->

Viel Spaß.

47
H.B.

Die Sichtbarkeit in DataGridTextColumn ist keine DependencyProperty und kann nicht datengebunden sein. Verwenden Sie eine DataGridTemplateColumn, und binden Sie die Sichtbarkeit der Steuerelemente in der Vorlage.

Bearbeiten: Eigentlich gilt diese Anweisung nur für Silverlight. Weitere Informationen finden Sie in dieser anderen SO Frage.

Wie DataGridColumn.Visibility binden?

Ich fragte nach dem einfachsten Weg, um festzustellen, ob eine Immobilie hier eine Abhängigkeit darstellt.

Wie kann ich am einfachsten feststellen, ob eine Eigenschaft eine Abhängigkeitseigenschaft ist?

4
Scott Munro

Ich würde einen eleganteren Ansatz bevorzugen, bei dem eine Freezable verwendet wird.

<Window.Resources>

    <DiscreteObjectKeyFrame x:Key="FlagKey" Value="{Binding Flag}"/>

</Window.Resources>


<DataGridTextColumn ... Visibility="{Binding Value, Source={StaticResource FlagKey}, ...}" />
4
AnjumSKhan

Lösungsvorschlag von H.B. ist wirklich gut und hat wahren WPF MVVM-Geist. Verwenden Sie es wo möglich.

In meinem speziellen Fall ist etwas schief gelaufen, und ich habe einen anderen Weg eingeschlagen, da mein Projekt kein strenges MVVM ist, sodass ich eine codierte Lösung verwenden kann.

In CustomView.xaml wird der Spalte folgender Name zugewiesen:

<DataGrid>
    <DataGrid.Columns>
        <DataGridTemplateColumn x:Name="MachinesColumn" ... />
        ...

In CustomView.xaml.cs haben wir eine einfache Eigenschaft, die die Sichtbarkeit der Spalte direkt ändert:

public Visibility MachinesColumnVisible
{
    get { return MachinesColumn.Visibility; }
    set
    {
        if (value == MachinesColumn.Visibility)
            return;
        MachinesColumn.Visibility = value;
    }
}
0
Anton Purin