Sharing columns or rows in a grid - wpf

I'm trying to create an asymmetrical layout using a Grid where i have 2 rows, 2 columns and an extra shared column as follows:
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle
Grid.Row="0"
Grid.Column="0"
Width="200"
Height="200"
Fill="Red" />
<Rectangle
Grid.Row="0"
Grid.Column="1"
Grid.ColumnSpan="2"
Width="250"
Height="200"
Fill="Blue" />
<Rectangle
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Width="250"
Height="200"
Fill="Yellow" />
<Rectangle
Grid.Row="1"
Grid.Column="2"
Width="200"
Height="200"
Fill="Green" />
</Grid>
But however i try to set it up, the second column always collapses unless i explicitly set a fixed width (in this case 50px). Why is this happening?
Shouldn't the second column resize itself to the remainder of each rectangle?

Using a Converter i managed to manually calculate the shared column size by placing the content of the first column in a container and binding the width of the shared column to the ActualWidth of that container subtracted by the first column width.
e.g.
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="{Binding ElementName=Rect3, Path=ActualWidth, Converter={StaticResource SharedColumnConverter}, ConverterParameter=200}" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle
Grid.Row="0"
Grid.Column="0"
Width="200"
Height="200"
Fill="Red" />
<Rectangle
Grid.Row="0"
Grid.Column="1"
Grid.ColumnSpan="2"
Width="250"
Height="200"
Fill="Blue" />
<Rectangle
Name="Rect3"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Width="250"
Height="200"
Fill="Yellow" />
<Rectangle
Grid.Row="1"
Grid.Column="2"
Width="200"
Height="200"
Fill="Green" />
</Grid>

Related

remove grid column on shift+space in a wpf application

I have a simple wpf application where I want to remove one column and have the remaining (in column 2) fill the window when ctrl+space is pressed. I've looked into keybinding and commands, but I can't figure this one out.
Code:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="24" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="268" MinWidth="188" MaxWidth="346"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Height="64" Width="5"/>
<Grid Grid.Row="0" Grid.Column="2"/>
<Label Grid.Row="0" Grid.Column="0" Content="Collections" FontFamily="Noto Sans" Foreground="#FF9B9B9B" FontSize="16" Name="TESTTEST" />
<Button Content="Add" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Right" Grid.ColumnSpan="2" Margin="0,7,3,0" />
</Grid>
<StatusBar Grid.Row="1" Background="#FF151515" Foreground="#FF636363" BorderBrush="#FF1D1D1D"/>
</Grid>

WPF Datagrid does not fill the entire height and width when maximizing window

My DataGrid is not taking the whole space when I maximize the window in my WPF application. This is how I created the layout:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" Width="265">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Date From:" />
<Label Grid.Row="1" Grid.Column="0" Content="Date To:" />
<DatePicker Grid.Column="1" Grid.Row="0" Margin="3" x:Name="DateFrom" />
<DatePicker Grid.Column="1" Grid.Row="1" Margin="3" x:Name="DateTo" />
<Button Grid.Column="1" Grid.Row="2" HorizontalAlignment="Right"
MinWidth="80" Margin="3" Content="Send" Click="PopulateGrid" x:Name="BtnPopulateGrid"/>
</Grid>
<StackPanel Grid.Row="0" Grid.Column="1">
<DataGrid Width="Auto" x:Name="Grid" Height="553"
Padding="10 0 0 0" VerticalScrollBarVisibility="Visible" Margin="10,0,-707,0" />
</StackPanel>
</Grid>
and this is how it looks like on regular size:
and this is how it looks like when window is max:
What can I try next? I am new to WPF.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Date From:" />
<Label Grid.Row="1" Grid.Column="0" Content="Date To:" />
<DatePicker Grid.Column="1" Grid.Row="0" Margin="3" x:Name="DateFrom" />
<DatePicker Grid.Column="1" Grid.Row="1" Margin="3" x:Name="DateTo" />
<Button Grid.Column="1" Grid.Row="2" HorizontalAlignment="Right" MinWidth="80" Margin="3" Content="Send" Click="PopulateGrid" x:Name="BtnPopulateGrid"/>
</Grid>
<Grid Grid.Row="0" Grid.Column="1">
<DataGrid x:Name="Grid" Padding="10 0 0 0" VerticalScrollBarVisibility="Visible" />
</Grid>
</Grid>
Firstly if you wanna make your datagrid fill a container automatically, you need to use Grid, not StackPanel also your datagrid sizes need to be set auto.
Edit:
As #Erjon said : You don't have to use a container when you have a single DataGrid.But if you have more components with your DataGrid, Grid will be a better container choice instead of StackPanel.
Your main GridDefination sizes were set as Auto, that was wrong.You need to work with "*" if you want a resposive design.Auto means that "Set this control's size with its children".
Try adding in the datagrid ColumnWidth="*"
It will expand all columns to avaiable space and the datagrid will fill it's parent
The second ColumnDefinition of the first grid should be <ColumnDefinition Width="*" />
And as #Zacos said in my answers comment you have to remove Width

Double Grid Splitter

I tried to implement a GridSplitter to my WPF Window - like shown here http://www.wpf-tutorial.com/panels/gridsplitter/
Worked just well. But I wanna do a double grid splitter. So the window should be splitted in a left and a right part. And the right part should be splitted in a top and a button part.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid></Grid>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">One</TextBlock>
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" />
<TextBlock Grid.Row="2" FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Two</TextBlock>
</Grid>
</Grid>
Buuut it alawys splits up the left part in two pieces. I tried like everything setting the Grid.Row and Grid.column for everything explicit - but nothing. What am I missing?
To achieve what you would like:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Left</TextBlock>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" />
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="5" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Top</TextBlock>
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" />
<TextBlock Grid.Row="2" FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Bottom</TextBlock>
</Grid>
</Grid>
You didn't set Grid.Column="2" on the the second Grid you intended to be on the right.
I also changed the Width and Height properties to * so the horizontal and vertical GridSplitters will sit in the center.

WPF, xaml grid with TabControl

I have an application (implemenented in WPF, XAML) which has 6 rows and 6 columns. At the position Grid.Row="1" Grid.RowSpan="4" Grid.Column="0" Grid.ColumnSpan="5" , I'm using a TabControl for Dashboard, Housekeeping, and Science. In every TabControl, I'm using a ListBox on the left side to choose individual data. The rest (w/o the ListBox) of the field/grid (which should have a size of 4 rows and 4 columns) is available for charts.
Problem
The charts which are visible in the screenshot below should be stretched over 4 rows down to the bottom edge of the application according to the XAML code. The TabControl is not 4 rows as visible because of the white boarder I have attached.
How can I change my grid-concept that it works as described above? Is a grid in the grid, resp. in the TabControl necessary at all?
Screenshot of the WPF application
MainWindow.xaml
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<!-- Definition of Rows and Columns -->
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="250" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<!-- Header -->
<StackPanel Grid.Row="0" Grid.ColumnSpan="6">
<TextBlock Text="RFM DATA ANALYZER" Margin="20" HorizontalAlignment="Center" FontSize="36" FontWeight="Thin" />
</StackPanel>
<!-- Tabs -->
<StackPanel Grid.Row="1" Grid.RowSpan="4" Grid.Column="0" Grid.ColumnSpan="5">
<TabControl TabStripPlacement="Top">
<TabItem Header="Dashboard">
<Border BorderBrush="White" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.RowSpan="4" Grid.Column="0" Grid.ColumnSpan="1">
<TextBlock Text="Data" Margin="0 50 0 20" HorizontalAlignment="Left" FontFamily="Segoe UI Semibold" FontSize="15" Foreground="LightGray" />
<ListBox >
<ListBoxItem Content="Data 00" />
<ListBoxItem Content="Data 01" />
<ListBoxItem Content="Data 03" />
</ListBox>
</StackPanel>
<oxy:PlotView Model="{Binding Model1}" Background="Transparent" Grid.Row="0" Grid.RowSpan="4" Grid.Column="1" Grid.ColumnSpan="1" />
<oxy:PlotView Model="{Binding Model2}" Background="Transparent" Grid.Row="0" Grid.RowSpan="4" Grid.Column="2" Grid.ColumnSpan="1" />
<oxy:PlotView Model="{Binding Model3}" Background="Transparent" Grid.Row="0" Grid.RowSpan="4" Grid.Column="3" Grid.ColumnSpan="1" />
<oxy:PlotView Model="{Binding Model4}" Background="Transparent" Grid.Row="0" Grid.RowSpan="4" Grid.Column="4" Grid.ColumnSpan="1" />
</Grid>
</Border>
</TabItem>
<TabItem Header="Housekeeping" Height="40">
<Border BorderBrush="White" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
etc.
Replace your StackPanels with Grids. StackPanels size to their child elements, whereas Grids size to their parent.
<StackPanel Grid.Row="1" Grid.RowSpan="4" Grid.Column="0" Grid.ColumnSpan="5">
<TabControl TabStripPlacement="Top">
...becomes...
<Grid Grid.Row="1" Grid.RowSpan="4" Grid.Column="0" Grid.ColumnSpan="5">
<TabControl TabStripPlacement="Top">

wpf gridlines - changing style

Is there any way to change the style of gridlines in wpf grid?
I need to divide grid into 4 cells. To do it I used RowDefinitions and ColumnDefinitions. However I need user to distinguish which cell is which, that's why I need to change the color of the gridlines.
It depends on the look you are going for. In WPF, there are different ways to do almost anything. Here are a couple of the easier ones.
The easiest way is to set ShowGridlines="True":
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="5"
ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0"
Text="(0,0)" />
<TextBlock Grid.Column="1"
Grid.Row="0"
Text="(1,0)" />
<TextBlock Grid.Column="0"
Grid.Row="1"
Text="(0,1)" />
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="(1,0)" />
</Grid>
That gives you grid something like:
You can also use a Rectangle in each cell of the grid to get different effects. Here, the Fill is transparent and the Stroke is Blue:
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Column="0"
Grid.Row="0"
Stroke="Blue"
Fill="Transparent" />
<TextBlock Grid.Column="0"
Grid.Row="0"
Text="(0,0)" />
<Rectangle Grid.Column="1"
Grid.Row="0"
Stroke="Blue"
Fill="Transparent" />
<TextBlock Grid.Column="1"
Grid.Row="0"
Text="(1,0)" />
<Rectangle Grid.Column="0"
Grid.Row="1"
Stroke="Blue"
Fill="Transparent" />
<TextBlock Grid.Column="0"
Grid.Row="1"
Text="(0,1)" />
<Rectangle Grid.Column="1"
Grid.Row="1"
Stroke="Blue"
Fill="Transparent" />
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="(1,0)" />
</Grid>
That produces this:
Alternatively, you can fill the Rectangles and not give them a Stroke:
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Column="0"
Grid.Row="0"
Fill="LightBlue" />
<TextBlock Grid.Column="0"
Grid.Row="0"
Text="(0,0)" />
<Rectangle Grid.Column="1"
Grid.Row="0"
Fill="LightYellow" />
<TextBlock Grid.Column="1"
Grid.Row="0"
Text="(1,0)" />
<Rectangle Grid.Column="0"
Grid.Row="1"
Fill="LightYellow" />
<TextBlock Grid.Column="0"
Grid.Row="1"
Text="(0,1)" />
<Rectangle Grid.Column="1"
Grid.Row="1"
Fill="LightBlue" />
<TextBlock Grid.Column="1"
Grid.Row="1"
Text="(1,0)" />
</Grid>
That can, for instance, give a checkerboard pattern:
This is by no means a comprehensive answer - you could probably fill a book. It was just meant to show that there are many ways to do what you are asking, and that there are some pretty quick and easy solutions if that's all you need.

Resources