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-wpfhttps://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