Collapse Control under a GridSplitter - Unwanted White space appears - c#

Given the following XAML;
<Grid>
<Grid.RowDefinitions>
<RowDefinition MinHeight="100"/>
<RowDefinition Height="2"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Background="LightBlue">
<Button Height="30"
Click="Button_Click">Hide Lower Panel</Button>
</Border>
<GridSplitter Grid.Row="1"
ResizeDirection="Rows"
Width="Auto"
HorizontalAlignment="Stretch"
Margin="0"
x:Name="Splitter"/>
<Border Grid.Row="2"
Background="LightCoral"
x:Name="LowerPanel" MinHeight="25"/>
</Grid>
Where Button_Click is;
this.LowerPanel.Visibility = this.LowerPanel.Visibility == Visibility.Visible
? Visibility.Collapsed
: Visibility.Visible;
This looks like this;
If the button is clicked before doing anything else, then it collapses as expected;
However, if I resize using the grid splitter..
Then when I press the button, the following happens;
Is there any way to make the lower element collapse correctly again after it has been resized?
Note: for the purposes of this question I've just used code-behind event handers and a button to trigger this, but in real-life it's done in the proper MVVM way with the visibility being determined by a bound property on the view model.

AFAIK, when GridSplitter is used, its rewrites the Height or Width properties of the corresponding RowDefinitions and ColumnDefinitions. In order to do what you want, you should to play with RowDefinitions.Height property, like this:
public MainWindow()
{
InitializeComponent();
//gr is the name of the Grid
basepr1 = gr.RowDefinitions[0].Height;
basepr2 = gr.RowDefinitions[2].Height;
}
static GridLength zero = new GridLength(0);
GridLength basepr1;
GridLength basepr2;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (this.LowerPanel.Visibility == Visibility.Visible)
{
this.LowerPanel.Visibility = Visibility.Collapsed;
basepr2 = gr.RowDefinitions[2].Height; // remember previos height
gr.RowDefinitions[2].Height = zero;
}
else
{
this.LowerPanel.Visibility = Visibility.Visible;
gr.RowDefinitions[2].Height = basepr2;
}
}

I think you need to mark one of the row definitions as '*':
<Grid.RowDefinitions>
<RowDefinition MinHeight="100"/>
<RowDefinition Height="2"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

Related

How to Move Button Beside Text Boxes in WPF using WrapPanel

I am new to WPF. I have a Button.I want to create Dynamic textBoxes.when ever I got the focus on dynamic textbox the button move to beside textbox. I dont know how to do this. please help me
<Grid Name="mymy" HorizontalAlignment="Left" Height="243" Grid.Column="0" Grid.Row="0" VerticalAlignment="Top" Width="263" Margin="462,105,0,0" Grid.RowSpan="2" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<WrapPanel Grid.Column="1" x:Name="abc" HorizontalAlignment="Left" Height="232" Margin="0,0,-250,-218" VerticalAlignment="Top" Width="262" Grid.Row="1"/>
</Grid>
<!--<DockPanel Name="mymy1" HorizontalAlignment="Left" Height="191" LastChildFill="True" Margin="424,94,0,0" VerticalAlignment="Top" Width="282" Grid.RowSpan="2"/>-->
.cs code
private void button_Click(object sender, RoutedEventArgs e)
{
txtSource = new TextBox();
txtSource.MinHeight = 15;
txtSource.Width = 100;
txtSource.Height = 25;
txtSource.Name = "txtSource";
//Binding txtBinding = new Binding("PurchaseOrder.PickupSrcCodeName"); /*txtBinding.Mode = BindingMode.OneWay;*/
//txtSource.SetBinding(TextBox.TextProperty, txtBinding);
ColumnDefinition colDef1;
colDef1 = new ColumnDefinition();
mymy.ColumnDefinitions.Add(colDef1);
RowDefinition rowDef1;
rowDef1 = new RowDefinition();
mymy.RowDefinitions.Add(rowDef1);
++count;
abc.Children.Add(txtSource);
Grid.SetColumn(txtSource, count);
Grid.SetRow(txtSource, 0);
txtSource.GotFocus += t_GotFocus;
txtSource.TextChanged += this.t_TextChanged;
}
private void t_TextChanged(object sender, RoutedEventArgs e)
{
button.Visibility = Visibility.Visible;
}
enter image description here
Welcome to SO.
Consider these two things:
It's extremely bad habit to change the layout of a grid at run time (and by layout I mean rows and columns)
Just the same way that you set your textboxes positions in your grid you can position your button within it as well. You just need to create the rows and columns required by it before head.
My opinion here is you should have a stack layout adding controls to it dynamically. That control then can be custom control consisting of a grid with a text box and a position for button (or maybe a button that can be hidden or visible with a property)
If you like my idea please see this to know how to create custom controls.

Storyboard targeting GridLength for WP8

I want to make a storyboard for RowDefinition changing the Height, and I found this to help me. The only problem when I want to create the class GridLengthAnimation, I cannot make it a AnimationTimeline. Is this because windows phone 8 does not support this?
In this case is there another work around for making a storyboard for RowDefinition?
Easiest way may be that you put grids to the rows, and animate their Height-property like this.
Here is the xaml:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Background="AliceBlue"
Grid.Row="0"
Height="100"
Tap="Grid_Tap"
CacheMode="BitmapCache" />
<Grid Background="AntiqueWhite"
Grid.Row="1"
Height="100"
Tap="Grid_Tap"
CacheMode="BitmapCache" />
<Grid Background="Aqua"
Grid.Row="2"
Height="100"
Tap="Grid_Tap"
CacheMode="BitmapCache" />
<Grid Background="Aquamarine"
Grid.Row="3"
Height="100"
Tap="Grid_Tap"
CacheMode="BitmapCache" />
</Grid>
And the cs:
private void AnimateHeight(Grid grid)
{
double newHeight = grid.ActualHeight == 100 ? 300 : 100; //select the height we want to animate
Storyboard story = new Storyboard();
DoubleAnimation animation = new DoubleAnimation();
animation.To = newHeight;
animation.Duration = TimeSpan.FromSeconds(0.5);
Storyboard.SetTarget(animation, grid);
Storyboard.SetTargetProperty(animation, new PropertyPath(Grid.HeightProperty));
story.Children.Add(animation);
story.Begin();
}
private void Grid_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Grid grid = sender as Grid; //select the grid we tapped
AnimateHeight(grid);
}
Notice that I putted cachemode to bitmapcache all of the grids. That's not necessary, but gives more fluent animation, because static grids won't be redrawed again in each frame.

How to get a Grid to raise MouseDown events when no UIElemets in cells clicked?

I observe Mouse.MouseDown and PreviewMouseLeftButtonDown are only raised when the mouse is clicked in a cell that contains a UIElement, e.g.:
XAML
<Window xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="WpfApplication5.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Width="300" Height="300">
<Grid Mouse.MouseDown="Grid_MouseDown" PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Rectangle Grid.Column="2" Grid.RowSpan="2" Fill="Red"/>
</Grid>
</Window>
Code-behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("PreviewMouseLeftButtonDown raised!");
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("MouseDown raised!");
}
}
The lines are only written to Debug when the red rectangle is clicked. How can I get the events, or at least one of them, to be raised the grid contains nothing?
I do not know the cause of the issue, but as a workaround giving the Grid a background, even Transparent, seems to make the events be raised!
<Grid Background="Transparent" Mouse.MouseDown="Grid_MouseDown" PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown">

WPF remove grid from window

I have this Grid in my WPF application :
<Grid Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="70" Name="BarRowDef" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Name="BarGrid" Grid.Row="0" Height="70" VerticalAlignment="Top" Background="#FF802C2C">
<Button Content="History" Focusable="False" Width="100" Height="60" HorizontalAlignment="Left" VerticalAlignment="Center" Name="HistoryButton" Click="HistoryButton_Click"/>
</Grid>
<Grid Name="MiddleGrid" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<WebBrowser HorizontalAlignment="Stretch" Name="Browser" VerticalAlignment="Stretch" LoadCompleted="Finish_Load" Grid.Column="1"/>
</Grid>
</Grid>
And i want to the browser will have full screen option. So what i done is in the event Of EnterFullscreen is called is :
BarRowDef.Height = new GridLength(0);
And what happen is that the Browser start from the top of the page but in the bottom i have a white space in the size of BarGrid.
Any idea what can be the problem?
Edit
This is the full EnterFullScreenMode method :
public void EnterFullScreenMode()
{
BarRowDef.Height = new GridLength(0);
if (this.WindowState == System.Windows.WindowState.Maximized)
{
this.WindowState = System.Windows.WindowState.Normal;
}
this.WindowStyle = System.Windows.WindowStyle.None;
this.WindowState = System.Windows.WindowState.Maximized;
IsFullScreen = true;
}
I believe setting to Visibility.Hidden can still result in some whitespace being rendered.
You can set the content of the row (BarGrid) to Collapsed, which means: "Do not display the element, and do not reserve space for it in layout".
BarGrid.Visibility = Visibility.Collapsed;
Edit: Additional details from comments
Also ensure the height setting removed from the RowDefinition.
Instead of:
<RowDefinition Height="70" Name="BarRowDef"/>
Use:
<RowDefinition Height="Auto"/>
I am not sure what do you mean, EnterFullscreen event of what?
You can try this:
BarGrid.Visibility = Visibility.Hidden;
instead of:
BarRowDef.Height = new GridLength(0);

WPF resizing, * vs Auto

I have a XAML with 2 columns in a Grid and I have a button that when I click it, in the code behind, I set the visibility to collapse, and want to resize the other half of the screen to try to take up the whole screen. The collapsing part works, and the RHS then shifts over to the LHS, but it does not take up the entire screen. I tried using both the Auto and Star to resize in HidePlots, but it never takes the full screen. I thought if I collapsed the LHS, and set the column to * for the RHS, it would take up the whole screen. Any thoughts? Thanks.
Here's some code to make it more clear:
<Grid Grid.Row="1" x:Name="ExpandableGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="1.5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" x:Name="TableGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Grid.Column="0" x:Name="SampleViewGroupBox" Header="SampleView" HorizontalAlignment="Stretch" FontFamily="Arial" FontSize="12" Margin="5,0,5,0" >
<ContentControl Content="{Binding LayoutManager.SampleView}" Height="Auto" Width="Auto"/>
</GroupBox>
<Button x:Name="TableButton" HorizontalAlignment="Right" Content="Button" Width="15" Height="15" VerticalAlignment="Top" Margin="0,0,-2,0" Click="MaxButton_Click" Grid.Column="0" Grid.Row="0"/>
</Grid>
<Grid Grid.Column="1" x:Name="BaseViewGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<GroupBox Grid.RowSpan="2" Grid.Column="1" Name="BaseViewGroupBox" Header="PLOTS" Margin="5,0,5,0" >
<ContentControl Content="{Binding LayoutManager.ConsensusView}" Height="Auto" Width="Auto" />
</GroupBox>
</Grid>
</Grid>
private void MaxButton_Click(object sender, RoutedEventArgs e)
{
UIElement senderElement = (UIElement)sender;
if (_tableMinimized)
{
HideTables(false);
_tableMinimized = false;
((Button)senderElement).Style = (Style)FindResource("DashboardDetailsButton");
}
else
{
HideTables(true);
_tableMinimized = true;
((Button)senderElement).Style = (Style)FindResource("DashboardDetailsButtonReverse");
}
}
private void HideTables(bool hide)
{
if (hide)
{
foreach (UIElement child in TableGrid.Children)
child.Visibility = Visibility.Collapsed;
for (int i = 0; i < ExpandableGrid.ColumnDefinitions.Count; i++)
ExpandableGrid.ColumnDefinitions[i].Width = GridLength.Auto;
ExpandableGrid.ColumnDefinitions[1].MinWidth = 500;
for (int i = 0; i < ExpandableGrid.RowDefinitions.Count; i++)
ExpandableGrid.RowDefinitions[i].Height = GridLength.Auto;
TableButton.Visibility = Visibility.Visible;
}
else
{
foreach (UIElement child in TableGrid.Children)
child.Visibility = Visibility.Visible;
for (int i = 0; i < ExpandableGrid.ColumnDefinitions.Count; i++)
ExpandableGrid.ColumnDefinitions[i].Width = new GridLength(1, GridUnitType.Star);
for (int i = 0; i < ExpandableGrid.RowDefinitions.Count; i++)
ExpandableGrid.RowDefinitions[i].Height = new GridLength(1, GridUnitType.Star);
}
}
Edit: I tried to also change one line to:
ExpandableGrid.ColumnDefinitions[1].MinWidth = System.Windows.SystemParameters.PrimaryScreenWidth-20;
instead of the hard-coded 500 value, it looks correct. However, if I try to click the button again to revert back to normal, the RHS takes up the bulk of the screen without getting back to its original position.
Your current column definition says to make Column B equal to 1.5 times the size of Column A, so even if ColumnB's content is hidden, the column will still take up 3/5 of the screen.
Change it so the column that collapses has a Width="Auto", and set it's Content's Width equal to whatever size it should be when it's expanded. If you want to keep the 1.5* default width, I'd recommend using something like a MathConverter to figure out what size it should be based on the parent Grid's width. I have the code for one posted here
<Grid x:Name="ParentGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid x:Name="RHS" Grid.Column="0" />
<!-- Collapse this Grid -->
<Grid x:Name="LHS" Grid.Column="1"
Width="{Binding ElementName=ParentGrid, Path=ActualWidth,
Converter={StaticResource MathConverter},
ConverterParameter=((#VALUE/5)*3)}" />
</Grid>
You need to set column 0 to be whatever you desire (Auto, 150, etc...) and set column 1 to be *.
It looks like your Grid is also within a Grid, so the parent's behavior also has to be taken into account.

Categories