Laden...

DataGrid Column Visibility - wie gestaltet sich hier das Binding?

Erstellt von GeneVorph vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.156 Views
G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 4 Jahren
DataGrid Column Visibility - wie gestaltet sich hier das Binding?

Hallo,

wie ich jetzt mehrfach gelesen habe, ist es nicht so ohne weiteres möglich die Visibility einer DataGridTemplateColumn /Textcolumn zu binden. Der Grund ist wohl darin zu suchen, dass - warum auch immer - die Columns nicht im VisualTree des DataGrids liegen. Damit ist dann ganz schnell klar, warum es auf alt hergebrachte Weise nicht funktionieren kann, da in diesem Fall auch kein Zugriff auf den DataContext mittels RelativeSource möglich ist. Soweit so gut.

Ich habe mehrere Lösungsvorschläge online gefunden, die sich im Prinzip alle auf zwei Lösungsansätze stützen:
a) ein Proxy-Objekt vom Typ FrameworkElement oder ContentControl, das den DataContext einer View bereitstellt und die Column-Visibility sozusagen "fernsteuert".

b) eine Relay-Klasse, die von Freezable erbt

Beide Ansätze können z. B. hier gefunden werden:
https://stackoverflow.com/questions/22073740/binding-visibility-for-datagridcolumn-in-wpf
https://www.technical-recipes.com/2017/binding-the-visibility-of-datagridcolumn-in-wpf-mvvm/

Ich versuche gerade Methode a) nachzuprogrammieren, kann aber beim besten Willen nicht feststellen, wo ich da einen Denkfehler(?) habe.

Hier mein Code:
MainWindow


<Window x:Class="VisualTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:VisualTest.ViewModels"
        xmlns:local="clr-namespace:VisualTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>
    
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BtVConverter"/>
    </Window.Resources>
    
    <Grid>
        <StackPanel>

            <FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
            
            <DataGrid ItemsSource="{Binding TheSource}" AutoGenerateColumns="False">
                
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Meine Objekte" Binding="{Binding Labeling}">
                        
                    </DataGridTextColumn>

                <!--Um diese Zeile geht es: das Binding funktioniert nicht! -->
                <DataGridTextColumn Header="Meine Werte" Binding="{Binding AValue}" Visibility="{Binding DataContext.IsVisible, Source={x:Reference dummyElement}}">
                <!-- Es macht hier keinen Unterschied ob ich DataContext.IsVisible habe, oder wie in einem Beispiel .IsEnable-->
                   
                </DataGridTextColumn>
                    
                </DataGrid.Columns>
                
            </DataGrid>
           
            <Rectangle Fill="Red" Width="20" Height="20" Visibility="{Binding IsVisible, Converter=   
                                                   {StaticResource BtVConverter}}"/>

            <CheckBox x:Name="ckbToggleVisibility" Content="Sichtbarkeit an/aus" Margin="20" IsChecked="{Binding IsVisible, Mode=OneWayToSource}">
                
            </CheckBox>

            <TextBlock Margin="30" Text="{Binding IsVisible, Mode=OneWay}">
             
            </TextBlock>
            
        </StackPanel>
    </Grid>
</Window>

Mein MainViewModel:


 public class MainViewModel : NotifyPropertyChangedBase
    {
        public ObservableCollection<MyObject> TheSource { get; set; } = new ObservableCollection<MyObject>();

        private bool _isVisible;
        public bool IsVisible
        {
            get { return _isVisible; }
            set
            {
                _isVisible = value;
                OnPropertyChanged(ref _isVisible, value);
            }
        }

        public MainViewModel()
        {
            MyObject o1 = new MyObject()
            {
                Labeling  = "Objekt 1",
                AValue = "Value 1"
            };

            MyObject o2 = new MyObject()
            {
                Labeling = "Objekt 2",
                AValue = "Value 2"
            };

            MyObject o3 = new MyObject()
            {
                Labeling = "Objekt 3",
                AValue = "Value 3"
            };

            MyObject o4 = new MyObject()
            {
                Labeling = "Objekt 4",
                AValue = "Value 4"
            };

            MyObject o5 = new MyObject()
            {
                Labeling = "Objekt 5",
                AValue = "Value 5"
            };

            MyObject o6 = new MyObject()
            {
                Labeling = "Objekt 6",
                AValue = "Value 6"
            };

            MyObject o7 = new MyObject()
            {
                Labeling = "Objekt 7",
                AValue = "Value 7"
            };

            TheSource.Add(o1);
            TheSource.Add(o2);
            TheSource.Add(o3);
            TheSource.Add(o4);
            TheSource.Add(o5);
            TheSource.Add(o6);
            TheSource.Add(o7);
        }

Mein Daten-Model (reiner Dummy, nur für Testzwecke)


public class MyObject
    {
        public string Labeling { get; set; }
        public string AValue { get; set; }
    }

Und nur der Vollständigkeit halber --> mein Codebehind


 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

Ich habe auf dem MainWindow eine Checkbox, deren IsChecked-Eigenschaft an ein Property des MainViewModels gebunden ist: IsVisible. Dieses ist vom Typ bool und soll eigentlich (bei geckeckter Checkbox) dafür sorgen, dass die Werte-Spalte im DataGrid auf "collapsed" gesetzt wird.

Unter dem DataGrid befindet sich ein rotes REctangle, das an die IsVisible-Eigenschat auf dem MainViewModel gebunden ist. Wird das Häkchen bei der Checkbox gesetzt, wird das Rectangle sichtbar.

Außerdem habe ich ein TextBlock, der an IsVisible gebunden ist, und den aktuellen Staus (true oder false) in Textform ausgibt.

Mein Problem: setze ich das Häkchen bei der Checkbox, wird zwar das Rectangle sichtbar, bzw. in der Textbox wird "true" angezeigt, die DataGridColumn bleibt aber unverändert.
An welcher Stelle in meinem Code habe ich einen Fehler?

viele Grüße
Vorph

3.170 Beiträge seit 2006
vor 4 Jahren

Hallo,

im gezeigten Code hast Du für das Binding an die DataGridTextColumn keinen Converter gesetzt, da versuchst Du also, ein bool an ein Element zu binden, dass eine Visibility erwartet.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 4 Jahren

Danke - das war in der Tat das Problem! Ich hatte jetzt so lange schon erfolglos hin und herprobiert, ich hätte das wahrscheinlich erst in ein paar Tagen bemerkt - wenn überhaupt^^

viele Grüße
Vorph

5.657 Beiträge seit 2006
vor 4 Jahren

erst in ein paar Tagen

Es muß doch irgendein Fehler kommen, wenn das Binding nicht funktioniert. Wenn etwas nicht funktioniert, kann man zielgerichtet danach suchen, siehe [Artikel] MVVM und DataBinding, Abschnitt Debugging

Weeks of programming can save you hours of planning