I have a WPF app with a main view of a treelist and I also want to be able to open a second component when I press on a button (and hide it when pressed again).
But I cannot make the second component to take the needed space and the tree view the rest, without overlapping.
In XAML, I declared a grid with 5 rows as follows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition />
<RowDefinition Height="auto"/>
<RowDefinition />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<views:InputsControl Grid.Row="0"/>
<views:TreeViewControl Grid.Row="1" />
<GridSplitter Grid.Row="2"
HorizontalAlignment="Stretch"
Height="3"
Visibility="{Binding LoggerVisibility}" >
</GridSplitter>
<TextBox Grid.Row="3"
BorderThickness="1"
Margin="2 ,0, 2, 2"
IsReadOnly="True"
Visibility="{Binding LoggerVisibility}">
Some logger info
</TextBox>
<views:StatusBar Grid.Row="4"/>
</Grid>
ViewModel:
private Visibility _LoggerVisibility = Visibility.Collapsed;
public Visibility LoggerVisibility
{
get => _LoggerVisibility;
set
{
_LoggerVisibility = value;
OnPropertyChanged(nameof(LoggerVisibility));
}
}
private void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public MainWindowViewModel()
{
Messenger.Default.Register<Actions>(this, ProcessAction);
}
private void ProcessAction(Actions action)
{
if (action == Actions.ToggleLogger)
{
if (LoggerVisibility == Visibility.Collapsed)
{
LoggerVisibility = Visibility.Visible;
}
else if (LoggerVisibility == Visibility.Visible)
{
LoggerVisibility = Visibility.Collapsed;
}
}
}
Here is how the app looks like:
So I want it to go the the layout in the first photo after the second click.
I noticed that I can get my desired behavior, in separate steps, if I change the row span for the tree list view row. If the logger is visible, the code from above works perfectly fine. If the logger is closed and I add Grid.RowSpan = "3" to the treelist row, is also looks good. So I figured I can bind the value of the rowspan in code behind and keep it synced with LoggerVisibility which is also toggled in code behind when the button is pressed.
But for some reason, the rowspan is not updated. I supposed the way I bind it is correct, since I did the same thing for the LoggerVisibility binding, and it does its job and the logger can indeed be collapsed or visible when the button is pressed.
Can you, please, help me?



The purpose of the
GridSpliteris to redistribute space between rows/columns. It does this by changing the size of its adjacent rows/columns. In other words, theGridSplitteroverwrites the original values of theRowDefinitionorColumnDefinition. This means you have to backup the originalGridLengthvalues and restore them if theGridSplitteris collapsed.The following example shows a simple attached behavior to handle this by setting/binding the
GridSplitterService.IsVisibleattached property on theGridSplitter.Because we can now introduce a boolean property to toggle the visibility from the view model the solution becomes cleaner in terms of MVVM.
ViewModel.cs
MainWindow.xaml
GridSplitterService.cs