WPF resizing, * vs Auto - c#

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.

Related

How to implement WPF custom grid with scrolling support

I asked a few months ago similarly question, but now I have different problem and I am not sure how to solve that.
Picture below describes what I want to implement - in fact I want DataGrid behavior. With 'fixed' keyword I mean that:
1) Header is always visible when I use vertical scrollbar, and header is moving if I use horizontal scrollbar
2) Rows are always visible when I use horizontal scrollbar, and rows are moving if I use vertical scrollbar
I need to create Grid on dynamically way, because I don't know number of rows or columns in advance.
My current solution doesn't include 'fixed rows' and my vertical scroll bar is not visible always (orange line at picture).
XAML
<Grid>
<Grid Grid.IsSharedSizeScope="True">
<ScrollViewer CanContentScroll="True" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" Grid.Row="2" Grid.ColumnSpan="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="600" />
</Grid.RowDefinitions>
<Grid x:Name="HeaderDaysGrid" Margin="10,0,0,0" Grid.Row="0" ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" MaxWidth="150"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
</Grid>
<Grid x:Name="SchedulerGridWrapper" Grid.Row="1" Margin="10,0,0,5">
<ScrollViewer x:Name="SchedulerScrolViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Height="600">
<Grid x:Name="WeekSchedulerGrid" ShowCustomGridLines="False" ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</Grid>
</Grid>
</ScrollViewer>
</Grid>
</Grid>
And in code behind I have something like this:
private void CreateWeekGrid()
{
WeekSchedulerGrid.Children.Clear();
WeekSchedulerGrid.RowDefinitions.Clear();
WeekSchedulerGrid.ColumnDefinitions.Clear();
HeaderDaysGrid.Children.Clear();
CreateColumnDefinition(WeekSchedulerGrid, NUMBER_OF_COLUMNS, GRID_COLUMN_WIDTH);
CreateRowDefinition(ref WeekSchedulerGrid, _numberOfRows);
for(int row = 0; row < _numberOfRows; row++)
{
TextBlock textBlock = new TextBlock { Text = "Some row name"};
Grid.SetRow(textBlock, row);
Grid.SetColumn(textBlock, 0);
WeekSchedulerGrid.Children.Add(textBlock);
}
foreach (var item in _headerList)
{
HeaderDaysGrid.Children.Add(item);
}
}
private void CreateRowDefinition(ref SchedulerGrid grid, int numberOfRows)
{
for (int row = 0; row < numberOfRows; row++)
{
RowDefinition gridRow = new RowDefinition();
gridRow.MinHeight = 100;
gridRow.MaxHeight = 300;
grid.RowDefinitions.Add(gridRow);
}
}
private void CreateColumnDefinition(ref SchedulerGrid grid, int numberOfColumns, int columnWidth)
{
for (int colIndex = 0; colIndex < numberOfColumns; colIndex++)
{
ColumnDefinition gridCol = new ColumnDefinition();
grid.ColumnDefinitions.Add(gridCol);
if (colIndex == 0)
{
gridCol.Width = new GridLength(1, GridUnitType.Star);
gridCol.MaxWidth = 150;
}
else
{
gridCol.Width = columnWidth;
}
}
}
With this solution I am not sure how to implement 'fixed rows' and to have functionalities described on the picture. Code behind, XAML and binding or something else?
I probably can't join 'fixed rows' and all cells in one grid - because of scroll bar. 'Fixed rows', 'fixed header' and 'all cells' needs to be separate grid? But how to create such a layout and desired behavior? I'm really not sure.
In addition, this custom grid is used like scheduler and shows some custom events(user controls) in his cells, so I probably can't use DataGrid. And sorry for bad English.
I resolved the problem on next way. I have three grids. If you look at the image 'Fixed header', 'Fixed rows' and 'Gray surface for content' are separate grids now.
Also I have three scroll viewers. Only the scroll viewer for content is visible. Other scroll viewers are set as hidden, but I update theirs values in code behind when content scroll viewer position is changed.
XAML
<Grid">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="HeaderDaysScrolViewer" CanContentScroll="True" Grid.Row="0" Grid.Column="1" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<Grid x:Name="HeaderDaysGrid" Margin="10,0,0,0" ShowGridLines="False"/>
</ScrollViewer>
<ScrollViewer x:Name="VerticalScrolViewer" CanContentScroll="True" Grid.Row="1" Grid.Column="0"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<Grid x:Name="VerticalDataGrid" ShowCustomGridLines="True" GridLineThickness="0.5" GridLineBrush="#FF434343"/>
</ScrollViewer>
<ScrollViewer x:Name="SchedulerScrolViewer" HorizontalScrollBarVisibility="Visible" VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Visible" ScrollChanged="SchedulerScrolViewer_ScrollChanged" Grid.Row="1" Grid.Column="1" Margin="10,0,0,5">
<Grid>
<Grid x:Name="WeekSchedulerGrid" ShowCustomGridLines="False" ScrollViewer.CanContentScroll="True"/>
</Grid>
</ScrollViewer>
</Grid>
Code behind
private void SchedulerScrolViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
HeaderDaysScrolViewer.ScrollToHorizontalOffset(e.HorizontalOffset);
OverviewTypesScrolViewer.ScrollToVerticalOffset(e.VerticalOffset);
}
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="HeaderDays" Height="35"/>
<RowDefinition x:Name="ScrollAreaRows" Height="600"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="HeaderRows" Width="35"/>
<ColumnDefinition x:Name="ScrollAreaColumns" Width="600"/>
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="DataScroller" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible" Grid.Row="1" Grid.Column="1">
<Grid x:Name="DataGrid" Height="{Binding Height, ElementName=ScrollAreaRows, UpdateSourceTrigger=PropertyChanged}" Widht="{Binding Width, ElementName=ScrollAreaColumns, UpdateSourceTrigger=PropertyChanged}">
</ScrollViewer>
the grid named "DataGrid" is the one that should scroll horizontally and vertically, while letting row0 and column0 of the outside grid to visually "stay static".

WPF how to cut stackpanel content?

I need to print some informations, and I have print preview page which contains:
<Grid Name="pageGrid" Width="Auto" Height="Auto" Margin="70">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="0" Name="headerGrid" Margin="0,0,0,5" />
<Grid Grid.Column="0" Grid.Row="1" Name="pageSummaryGrid" Margin="0" />
<Grid Grid.Column="0" Grid.Row="2" Name="dataGrid" Margin="0" />
<Grid Grid.Column="0" Grid.Row="3" Name="footerGrid" Margin="0,5,0,0" VerticalAlignment="Bottom" />
</Grid>
The header and footer exists on every page. pageSummaryGrid and dataGrid may be populated. Also I have this code which populate print details:
pageCount = pages.Count;
for (int i = 0; i < pageCount; i++)
{
myPage = new PrintPreviewPage();
header = new PrintPageHeader();
footer = new PrintPageFooter();
CreateHeaderAndFooter(i + 1, pageCount, header, footer);
myPage.SetHeader(header);
myPage.SetTableData(pages[i]);
myPage.SetFooter(footer);
pageList.Add(myPage);
}
Methods:
public void SetTableData(Panel panel)
{
dataGridGrid.Children.Add(panel);
}
public void SetHeader(FrameworkElement header)
{
headerGrid.Children.Add(header);
}
public void SetFooter(FrameworkElement footer)
{
footerGrid.Children.Add(footer);
}
pages is list of StackPanel(represent print details, for example some pictures,list etc.) When some pages[i] is larger than real page height then the footer becomes invisible and print details(list,pictures etc.) is cutted(footer is pushed).
I want that footer is always visible, and if I need to cut just print details. I tried to set MaxHeight, Height, ActualHeight and ClipToBounds properties of StackPanel, but nothing works. Any idea?

C# Universal App: Image foreground while dragging

I have this puzzle game where I can movie pieces on the playfield.
I recently added a touchscreen way to do that, it works, but there is an issue.
When I move an image from one place to another, the dragged image is in the background, the other images are in the foreground, I would like to have it the other way, see Screenshot. 1
My delta function is this:
public void Touch_Delta(object sender, Windows.UI.Xaml.Input.ManipulationDeltaRoutedEventArgs e)
{
Image img_touched = (Image)sender;
TranslateTransform _Transform = (img_touched.RenderTransform = (img_touched.RenderTransform as TranslateTransform) ?? new TranslateTransform()) as TranslateTransform;
_Transform.X += e.Delta.Translation.X;
_Transform.Y += e.Delta.Translation.Y;
if(_Transform.X > 90.0)
{
img_touched.RenderTransform = null;
Move_Right(this, null);
}
else if(_Transform.X < -90)
{
img_touched.RenderTransform = null;
Move_Left(this, null);
}
else if (_Transform.Y > 90.0)
{
img_touched.RenderTransform = null;
Move_Down(this, null);
}
else if (_Transform.Y < -90.0)
{
img_touched.RenderTransform = null;
Move_Up(this, null);
}
Rotate_Touch += e.Delta.Rotation;
if(Rotate_Touch > 55.0)
{
Rotate_Right(this, null);
Rotate_Touch = 0;
}
else if(Rotate_Touch < -55.0)
{
Rotate_Left(this, null);
Rotate_Touch = 0;
}
}
The corresponding XAML is this:
<UserControl
x:Class="PictureSplitter.Views.PictureView"
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"
mc:Ignorable="d"
d:DesignHeight="768"
d:DesignWidth="1024">
<Grid Height="1000" Width="600" Background="Black">
<GridView ItemsSource="{Binding Splitter.PuzzlePositions}" Background="Black">
<GridView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="#FF888E91" BorderThickness="2" Background="Black">
<Grid Name="picGrid" Background="Black" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="{Binding Piece.ImageSource}" Tapped="Image_Tapped" ManipulationMode="All" CanDrag="False" Loaded="Load_Events" />
</Grid>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</UserControl>
I know there is a zindex in the Windows.Canvas thing, but I haven't found something similar here. Is there a way to do this?
Well normally if there is no z-index the elements will follow the z order they were written/generated - I guess if you try to move the 3rd element onto the 2nd one it'd be on top of it :)
Now without using canvas I don't think you can do this, because even the new Transform3D stuff respects the original Z order, so if you'd move one item "above" the others (translate-z: +1) it would still be drawn behind the next ones.
With all this: use a canvas - It's better for a game anyway ;)

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);

Silverlight: Add border around grid

I have a grid that I need to put into a border, doing this via XAML is easy
but how do I do this via C#?
everything that I have found thus far wants to add the border around each cell.
I need it to come out looking the same way XAML does it, please help!
I can not get the XAML to post correctly here:
<Border Grid.Column="1"
Grid.Row="0"
Background="AliceBlue"
BorderBrush="Black"
BorderThickness="4"
x:Name="Side6"
Visibility="Collapsed">
<UIElement.Projection>
<PlaneProjection RotationY="-90" />
</UIElement.Projection>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Column="2" Grid.Row="1" Click="RotateRight_Click">
<Button.Content>
<StackPanel>
<TextBlock HorizontalAlignment="Center">Rotate Right</TextBlock>
<TextBlock HorizontalAlignment="Center">To</TextBlock>
<TextBlock HorizontalAlignment="Center">Side 4</TextBlock>
</StackPanel>
</Button.Content>
</Button>
<Button Grid.Column="0" Grid.Row="1" Click="RotateLeft_Click">
<Button.Content>
<StackPanel>
<TextBlock HorizontalAlignment="Center">Rotate Left</TextBlock>
<TextBlock HorizontalAlignment="Center">To</TextBlock>
<TextBlock HorizontalAlignment="Center">Side 2</TextBlock>
</StackPanel>
</Button.Content>
</Button>
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="1"
Text="Side 6">
</TextBlock>
</Grid>
</Border>
Here is the C# code that I'm using, maybe you can see what I am doing wrong?
public static void panelMain(string strPassGridName, System.Windows.Media.Color mcPassColor,
int intRowProperty, int intColumnProperty, Visibility vVisibility,
string[] strButtonTitles, Grid passLayoutRoot, Canvas passCanvas)
{
Grid panelGrid = new Grid();
panelGrid.Name = strPassGridName;
panelGrid.Background = new SolidColorBrush(mcPassColor);
panelGrid.SetValue(Grid.RowProperty, intRowProperty);
panelGrid.SetValue(Grid.ColumnProperty, intColumnProperty);
panelGrid.Visibility = vVisibility;
RowDefinition row1 = new RowDefinition();
row1.Height = new GridLength(100, GridUnitType.Auto);
panelGrid.RowDefinitions.Add(row1);
ColumnDefinition column1 = new ColumnDefinition();
column1.Width = new GridLength(100);
panelGrid.ColumnDefinitions.Add(column1);
passLayoutRoot.Children.Add(panelGrid);
}
I figured it out, I needed to create the border first then add the grid to the border.
One major difference is that I could not reference the border object directly, I needed to "find it"
Border findBorder = passLayoutRoot.FindName("bd" + strPassGridName) as Border;
if (findBorder == null)
{ }
else
{
findBorder.Child = panelGrid;
}
This worked perfectly....
Thanks to all that attempted to help
You can do it as below,
Border gridBorder = new Border();
gridBorder.BorderBrush = new SolidColorBrush(Colors.Black);
gridBorder.BorderThickness = new Thickness(4);
gridBorder.Child = new Grid(); //Your grid here
LayoutRoot.Children.Add(border); // ParentGrid(layout) holding the border

Categories