I have a ScrollViewer that contains a Grid of images. I am not sure if using a grid is the correct choice. Here is a mockup image of what I want it to look like:
The red box represents the ScrollViewer. Inside it, is some type of layout container (Grid at the moment) that has two rows of images (green squares) but a dynamic amount of columns that can change at runtime, that can be scrolled to. Another condition is that I want to resize them so that 6 images (and only 6!) are always visible.
So in XAML:
<ScrollViewer Name="scrollViewer1">
<Grid Name="grid1"></Grid>
</ScrollViewer>
Then using C# I think I need to dynamically add columns. Then listening to scrollViewer1's SizeChanged event I need to dynamically calculate the size of the rows and columns so that 3 images are always in view. For example:
ColumnDefinition gridColN = new ColumnDefinition();
grid1.ColumnDefinitions.Add(gridColN);
Problem #1: Dynamically adding more columns makes the grid cells keep getting smaller and smaller and never scroll within the ScrollViewer until there are 10+ columns.
Expected result: The end result should be a horizontal stream of images, 6 visible at a time, that will resize when the outter container or window is resized. I am trying to size their width dynamically, but setting them to 1/3 of the containers width does not work.
Questions: Is this the correct approach? Should I use Grid inside the ScrollViewer? Do I have to manually calculate the sizes or is there a way to let them fill the container?
Grid width should be calculated as
grid1.Width = (scrollViewer1.ViewportWidth / 3) * grid1.ColumnDefinitions.Count;
grid1.Height = (scrollViewer1.ViewportHeight / 2) * grid1.RowDefinitions.Count;
This seemed to work for me:
XAML:
<DockPanel>
<ListBox Width="150" DockPanel.Dock="Left" BorderBrush="AliceBlue" BorderThickness="2">
<Button Name="AddColumn_Button" Width="100" Height="25" Content="Add Column" Click="AddColumn_Button_Click" Margin="5"/>
<Button Name="AddRow_Button" Width="100" Height="25" Content="Add Row" Margin="5" Click="AddRow_Button_Click" />
</ListBox>
<ScrollViewer Name="scrollViewer1" BorderBrush="AliceBlue" BorderThickness="2" SizeChanged="scrollViewer1_SizeChanged" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Margin="1">
<Grid Name="grid1" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</ScrollViewer>
</DockPanel>
CODE BEHIND:
private void scrollViewer1_SizeChanged(object sender, SizeChangedEventArgs e)
{
SizeGrid();
}
private void AddColumn_Button_Click(object sender, RoutedEventArgs e)
{
ColumnDefinition gridColN = new ColumnDefinition();
grid1.ColumnDefinitions.Add(gridColN);
SizeGrid();
}
private void AddRow_Button_Click(object sender, RoutedEventArgs e)
{
RowDefinition row = new RowDefinition();
grid1.RowDefinitions.Add(row);
SizeGrid();
}
private void SizeGrid()
{
grid1.Width = (scrollViewer1.ViewportWidth / 3) * grid1.ColumnDefinitions.Count;
grid1.Height = (scrollViewer1.ViewportHeight / 2) * grid1.RowDefinitions.Count;
}
Related
I have a main window written in WPF that contains three sub windows and a user control with buttons. It looks like this:
What I want to do is to have the sub windows' ratio and the buttons' position fixed proportionally with the main window resizing.
I've handled the sub windows' size ratio, but I can't keep the buttons on the left side when the main widow's width is expanded:
And here is my code:
private void MainWindowResize(object sender, SizeChangedEventArgs e)
{
// sub windows size ratio
formA.Height = (this.ActualHeight - 80) * 0.5;
formA.Width = this.ActualWidth;
formB.Height = (this.ActualHeight - 80) * 0.5;
formB.Width = this.ActualWidth * 0.5;
formC.Height = (this.ActualHeight - 80) * 0.5;
formC.Width = this.ActualWidth * 0.5;
// buttons will not move to the left with this code
btnFrame.Width = this.ActualWidth;
}
+) WPF code:
MainWindow
<Grid x:Name="maingrid">
<DockPanel x:Name="panel1" LastChildFill="false">
<Frame DockPanel.Dock="Bottom" Height="35" Width="800" Source="pack://application:,,,/FormBottom;component/form_bottom.xaml" />
<WindowsFormsHost x:Name="formA" DockPanel.Dock="Top" Height="207" Width="800" >
<wftop:form_top x:Name="formTop" Dock="Fill"/>
</WindowsFormsHost>
<WindowsFormsHost x:Name="formB" DockPanel.Dock="Left" Height="207" Width="400" >
<wflt:form_left x:Name="formLeft" Dock="Fill"/>
</WindowsFormsHost>
<WindowsFormsHost x:Name="formC" DockPanel.Dock="Left" Height="207" Width="400">
<wfrt:form_right x:Name="formRight" Dock="Fill"/>
</WindowsFormsHost>
</DockPanel>
<DockPanel x:Name="panel2" LastChildFill="false" >
<Frame DockPanel.Dock="Bottom" Height="35" Width="800" Source="pack://application:,,,/FormBottom;component/form_bottom.xaml" />
</DockPanel>
</Grid>
btnFrame
<UserControl x:Class="FormBottom.form_bottom"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FormBottom"
mc:Ignorable="d"
Height="35" Width="800">
<StackPanel x:Name="bottompanel" Orientation="Horizontal" Height="35" VerticalAlignment="Bottom">
<Button Content="Panel1" MinWidth="70" Click="Button_Click" />
<Button Content="Panel2" MinWidth="70" Click="Button_Click_1" Margin="10,0,0,0" />
</StackPanel>
</UserControl>
Is there a way to have the buttons fixed on the left?
You do not have size control on your own. WPF provides various Panels for layouting out-of-the-box and there are also panels for proportional layouts like Grid or DockPanel.
Your example could look like this in XAML. The Rectangles represent your views. Using Grid panel you can define rows and columns and via their RowDefinition and ColumnDefinition you can set Height and Width to either explicit sizes, e.g. 100, let the size be determined automatically to fit the content with Auto or set star-sizes like 2* which lets you define proportions. The default value is * so in the layout below, the last row sizes to its content and the other rows are sized in proportion 1:1.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Fill="Pink"/>
<Rectangle Grid.Row="1" Grid.Column="0" Fill="MediumSeaGreen"/>
<Rectangle Grid.Row="1" Grid.Column="1" Fill="LightBlue"/>
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<Button Content="A" Width="100" Height="50"/>
<Button Content="B" Width="100" Height="50" Margin="10, 0, 0, 0"/>
</StackPanel>
</Grid>
You can achieve the same layout with different panels, so this is just an example. What is the most suitable approach depends on your requirements and preferences. The same layout in code:
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
var pinkRectangle = new System.Windows.Shapes.Rectangle { Fill = Brushes.Pink };
grid.Children.Add(pinkRectangle);
Grid.SetRow(pinkRectangle, 0);
Grid.SetColumn(pinkRectangle, 0);
Grid.SetColumnSpan(pinkRectangle, 2);
var greenRectangle = new System.Windows.Shapes.Rectangle { Fill = Brushes.MediumSeaGreen };
grid.Children.Add(greenRectangle);
Grid.SetRow(greenRectangle, 1);
Grid.SetColumn(greenRectangle, 0);
var blueRectangle = new System.Windows.Shapes.Rectangle { Fill = Brushes.LightBlue };
grid.Children.Add(blueRectangle);
Grid.SetRow(blueRectangle, 1);
Grid.SetColumn(blueRectangle, 1);
var buttonA = new Button
{
Content = "A",
Width = 100,
Height = 50
};
var buttonB = new Button
{
Content = "B",
Width = 100,
Height = 50,
Margin = new Thickness(10, 0, 0, 0)
};
var stackPanel = new StackPanel { Orientation = Orientation.Horizontal };
grid.Children.Add(stackPanel);
Grid.SetRow(stackPanel, 2);
Grid.SetColumn(stackPanel, 0);
Grid.SetColumnSpan(stackPanel, 2);
stackPanel.Children.Add(buttonA);
stackPanel.Children.Add(buttonB);
I don't know what kind of control the btnFrame is but you can put the buttons inside of a e.g. StackPanel and set the HorizontalAlignment="Left" on it.
Your WPF code would be helpful to provide a better answer.
After you've posted your WPF I think you should just remove the Width="800" attribute from your Frame so that it always stretches to fit its containing DockPanel. Besides I can't see where the btnFrame name is set in the WPF.
Here I have the following simple window:
The upper part is a DataGrid, below is a TextBox. The window is set to size to content's width. This is the desired layout.
Now I need to display some richtext so I replace the TextBox with RichTextBox. The problem is that now the window stretches to the width of the screen, like so (I've shrunk it, of course, but you get the idea):
I've tried binding the RichTextBox's width to the actual width of the parent:
<RichTextBox Width="{Binding ElementName=Wrapper, Path=ActualWidth}"/>
but it still expands to the entire window. BTW the same happens if I use TextBox in the above code.
How can I make the RichTextBox's width fit to the parent, while still maintaining dynamic window layout? I mean the DataGrid is the key element to which both the windows's width and the RichTextBox's width must be subject to.
Below is the full code.
XAML
<Window x:Class="RichTextBox_Wrap.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:local="clr-namespace:RichTextBox_Wrap"
mc:Ignorable="d"
SizeToContent="Width"
Title="MainWindow" Height="250" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/>
<RowDefinition/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0"
HeadersVisibility="Column"
CanUserAddRows="False"
ItemsSource="{Binding Items}">
</DataGrid>
<StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Info" />
</StackPanel>
<DockPanel x:Name="Wrapper" Grid.Row="2">
<Border BorderBrush="CadetBlue" BorderThickness="1">
<RichTextBox />
</Border>
</DockPanel>
</Grid>
</Window>
C#
public class Item
{
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
}
public class ViewModel
{
public ObservableCollection<Item> Items { get; set; }
public ViewModel()
{
Items = new ObservableCollection<Item>
{
new Item {Name = "Apple", Description="Fruit", Price=3},
new Item {Name = "Banana", Description="Fruit", Price=5},
new Item {Name = "Tomato", Description="Vegetable", Price=4},
};
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
SOLUTIONS
1.
mm8's solution almost works but it seems that Loaded event happens to early to calculate the ActualWidth properly - the RichTextBox doesn't fill the width and leaves gaps. But taking the idea further I used the window's "Content_Rendered" event to fix the window's width and then set RichTextBox's width to auto.
<RichTextBox x:Name="RichBox" Grid.Row="1" MinHeight="75" Width="0" Visibility="Hidden" />
private void Window_ContentRendered(object sender, EventArgs e)
{
var window = sender as Window;
window.SizeToContent = SizeToContent.Manual;
window.Width = window.ActualWidth;
RichBox.Width = double.NaN;
RichBox.Visibility = Visibility.Visible;
}
2. Spongebrot was spot on. Indeed, when the extra border is removed binding to parent's ActualWidth works. But in real life my control is more complex and the border is there for a reason. But this can be solved by cascading bindings:
<DockPanel x:Name="Wrapper" Grid.Row="2" >
<Border x:Name="MyBorder" BorderBrush="CadetBlue" BorderThickness="1" Width="{Binding ElementName=Wrapper, Path=ActualWidth}" >
<RichTextBox x:Name="RichBox" Width="{Binding ElementName=MyBorder, Path=Width}" />
</Border>
</DockPanel>
It seems that binding to ActualWidth doesn't work as expected if you bind to a grandparent or more distant ancestor. This is seemingly why Sinatr's suggestion doesn't work either.
An easy workaround would be to set the Width of the RichTextBox to 0 in the XAML markup and then handle its Loaded event and set the Width to the window's width once it has been loaded:
<RichTextBox Width="0" Loaded="RichTextBox_Loaded" />
private void RichTextBox_Loaded(object sender, RoutedEventArgs e)
{
RichTextBox rtb = sender as RichTextBox;
rtb.Width = this.Width;
}
SizeToContent="Width"
So you want the window to autosize to DataGrid width?
RichTextBox seems special, it will request maximum available space from its parent container, occupying the whole combined desktops width at will. An easy fix is to limit width of it:
<Grid>
<DataGrid x:Name="dataGrid" />
<DockPanel>
<Border>
<RichTextBox Width="{Binding ActualWidth, ElementName=dataGrid}" />
</Border>
</DockPanel>
</Grid>
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.
I have a very simple XAML
<ui:BorderedGrid>
<ui:BorderedGrid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</ui:BorderedGrid.RowDefinitions>
<ui:BorderedGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</ui:BorderedGrid.ColumnDefinitions>
<StackPanel Background="Blue" VerticalAlignment="Top" Grid.Row="0" Grid.Column="0" Margin="5" Width="200" Height="70"></StackPanel>
<StackPanel Background="Red" VerticalAlignment="Top" Grid.Row="1" Grid.Column="0" Margin="5" Grid.RowSpan="2" Width="200" Height="300"></StackPanel>
<StackPanel Background="Plum" VerticalAlignment="Top" Grid.Row="0" Grid.Column="1" Margin="5" Grid.RowSpan="2" Width="200" Height="150"></StackPanel>
<StackPanel Background="SaddleBrown" VerticalAlignment="Top" Grid.Row="2" Grid.Column="1" Margin="5" Width="200" Height="250"></StackPanel>
</ui:BorderedGrid>
The BorderedGrid is just an extended version of WPF standard Grid, which have overriden OnRender function to draw column and row lines. Following is it's implementation
public class BorderedGrid : Grid
{
protected override void OnRender(DrawingContext dc)
{
double leftOffset = 0;
double topOffset = 0;
System.Windows.Media.Pen pen = new System.Windows.Media.Pen(System.Windows.Media.Brushes.LightGray, 1);
pen.Freeze();
foreach (RowDefinition row in this.RowDefinitions)
{
dc.DrawLine(pen, new System.Windows.Point(0, topOffset), new System.Windows.Point(this.ActualWidth, topOffset));
topOffset += row.ActualHeight;
}
// draw last line at the bottom
dc.DrawLine(pen, new System.Windows.Point(0, topOffset), new System.Windows.Point(this.ActualWidth, topOffset));
foreach (ColumnDefinition column in this.ColumnDefinitions)
{
dc.DrawLine(pen, new System.Windows.Point(leftOffset, 0), new System.Windows.Point(leftOffset, this.ActualHeight));
leftOffset += column.ActualWidth;
}
// draw last line on the right
dc.DrawLine(pen, new System.Windows.Point(leftOffset, 0), new System.Windows.Point(leftOffset, this.ActualHeight));
base.OnRender(dc);
}
}
The problem is, I am assuming the output should be like this
But the actual output is like this
My question is why this white space is left in first row? I think I am missing very simple thing.. :(
All the rows need to be aligned irrespective of columns. Since the height of row 0 is auto. Its actual height becomes the height of its tallest child element + margin, which will be a portion of the plum height + 10 (from margin).
Since the height (70) of the blue panel is shorter than the height of its row (row 0) and it is vertical aligned to the top, you get the the white space below it.
I believe the result you are seeing is what is expected based on your configuration of rows, row spans, height, etc.
In a way, your horizontal grid lines already hinted at the computed row heights.
Here is another way to look at it:
Height of row 2 is height of SaddleBrown
Height of row 1 is height of row 2 minus height of Red
Height of row 0 is height of Plum minus height of row 1
Height of row 0 is great than the height of Blue. Blue is vertical aligned to the top and therefore has a white space below it.
I try not to spend too much time fighting with WPF's Auto. It seems like your two columns are largely independent in terms of their layout. You could do something like this, basically rendering two independent columns:
<ui:BorderedGrid>
<ui:BorderedGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</ui:BorderedGrid.ColumnDefinitions>
<StackPanel Width="200" Grid.Column="0">
<StackPanel Background="Blue"Margin="5" Height="70"></StackPanel>
<StackPanel Background="Red" Margin="5" Height="300"></StackPanel>
</StackPanel>
<StackPanel Width="200" Grid.Column="1">
<StackPanel Background="Plum" Margin="5" Height="150"></StackPanel>
<StackPanel Background="SaddleBrown"Margin="5" Height="250"></StackPanel>
</StackPanel>
</ui:BorderedGrid>
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.