How to resize the usercontrol in wpf resizing - wpf

In my wpf project I have one main window(Mainwindow.xaml) file and remaining all windows are user controls. If I click any menu of the mainwindow.xaml then the corresponding usercontrols will appear in the mainwindow.xaml form.
My requirement is, when the usercontrol window is resized, I need to resize all controls width (i.e textboxes,comoboxes,..etc). How can I achieve this.

First of all, the components you need to resize dynamically should not have fixed sizes. You should put everithing into Grid and set width/height to "Auto"/"x*"/ Alignment to stretch...
<UserControl ...>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/><!--2/5 of total height-->
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Grid.Row="1">Text </TextBlock>
<TextBox Grid.Column="2" >Enter</TextBox>
<TextBox Grid.Row="2" Grid.ColumnSpan="2">Button 5 Button 5 Button 5 Button 5</TextBox>
</Grid>
</UserControl>
Main
<Grid Width="Auto" HorizontalAlignment="Stretch">
<ContentControl ..." />
</Grid>

Related

Auto Width ListBox with a ScrollBar

The code below and screenshots show the issue I'm having below.
I need to have a listbox with Width set to Auto as the content size is variable. However, the number of items going into the listbox will also change, so sometimes a ScrollBar will be needed. The problem is, Auto Width doesn't seem to play well with a Scrollbar as per the images below. I could add a margin but I do not want a gap when no scroll bar is required.
I notice that this is only a problem when the textbox has a long string placed in it, if there is a short/no string entered, then the scrollBar presents correctly.
Is there a way to do this other than detecting if a ScrollBar is needed and dynamically adding a margin? I feel like there should be a way to achieve this in my XAML while still keeping the listbox column to be Width=Auto.
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 200; i++)
{
lbxDocs.Items.Add("TESTSTRING"+i);
}
txtImagePath.Text =
#"uPPvU18ijL9Tz6fqvwLsymkdxuS8h8jS9afzQ8i7LLXvrb2JO2hmPImVF5Dq5PZpdOkw2sTX9j6GeGL7IsaDuaf1ltY0MdzCRHGTZlUVkMa43meW3gavXAWMHyLPiyfGlHxuXcQOoH8ldxkYuxhVRcSJY3ZyCzlCsPjWuINTQyJCAU5hiDqroXWI8"+
"uPPvU18ijL9Tz6fqvwLsymkdxuS8h8jS9afzQ8i7LLXvrb2JO2hmPImVF5Dq5PZpdOkw2sTX9j6GeGL7IsaDuaf1ltY0MdzCRHGTZlUVkMa43meW3gavXAWMHyLPiyfGlHxuXcQOoH8ldxkYuxhVRcSJY3ZyCzlCsPjWuINTQyJCAU5hiDqroXWI8";
}
<Window x:Class="Grid_ScrollBar.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:Grid_ScrollBar"
mc:Ignorable="d" Loaded="MainWindow_OnLoaded"
TextOptions.TextRenderingMode="ClearType" WindowStartupLocation="CenterScreen"
TextOptions.TextFormattingMode="Display" Height="400" Width="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="txtImagePath"/>
<ListBox Name="lbxDocs" Grid.Column="1" Grid.Row="1"/>
</Grid>
</Window>
Scroll Bar is cut off;
Once we hit the longer string item in the ListBox the width increases to show the rest of the scrollbar;
The problem is that you are telling to your textbox to take all the available space, i.e. all the space left by your ListBox. Now since the firsts elements of your listbox take "less" space, WPF grant them the minimum space possible, and it doesn't take in count the scrollbar size.
When you have this kind of problem (size of content that can very) my best advice is to not set width to auto. Instead go with proportional sizing (this will avoid also the the effect of physically shift columns to make more room for your listbox items).
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="9*"/>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="txtImagePath" Grid.Column="0" Grid.Row="0" TextWrapping="Wrap" Margin="0,0,10,0"/>
<ListBox Name="lbxDocs" Grid.Column="1" Grid.Row="1" />
</Grid>
you can add also TextWrapping="Wrap" to show the full text.
However if you really want to keep the width to auto you can force wpf to take in count the scrollbar using
<ScrollViewer Grid.Column="1" Grid.Row="1">
<ListBox Name="lbxDocs"/>
</ScrollViewer>
EDIT: to fix the problem with the scrollviewer you need to set the height of the listbox to the heigh of the scrollviewer, or the Auto setting will not work:
<ScrollViewer x:Name="test" Grid.Column="1" Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ListBox Name="lbxDocs" Height="{Binding ElementName=test, Path=ActualHeight}"/>
</ScrollViewer>
try adding the scrollview to your listview without changing the rest of xaml
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="txtImagePath"/>
<ListBox Name="lbxDocs"
Grid.Column="1"
Grid.Row="1"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
/>
Width = "*" means you will use all the rest of the available space.
Width = "Auto" means you will adjust the size of your content so that everything fits and not over any excess space
so (as you did) in your window will be column 1 adjusted to the size of the listview and column 0 with the rest of the window.

Scroll bar for user control in Silverlight

I've got a user control defined as this:
<UserControl
x:Class="Client.UserControl1"
d:DesignWidth="640" d:DesignHeight="480" MinWidth="400" MinHeight="400"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<RichTextBox Margin="10" Grid.Row="1" HorizontalScrollBarVisibility="Auto">
<Paragraph><Run Text="RichTextBox"/></Paragraph>
</RichTextBox>
<sdk:Label Margin="0" Height="24" HorizontalAlignment="Center"
Content="Message"/>
</Grid>
</UserControl>
I then use this control in a page as follows:
<navigation:Page
Style="{StaticResource PageStyle}" ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<Grid x:Name="LayoutRoot" Background="Blue"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Client:UserControl1 Margin="10"/>
</Grid>
</navigation:Page>
I want the user control to fill the page. As the page expands, so does the user control. This works fine. However, I specify a minimum height and width for the user control. If the page is smaller than this, I want scroll bars to be shown. However, when I make the page smaller than the minimum size, no scrollbars appear.
I've tried wrapping the user control in a scrollviewer, but this does not give me the behaviour I want. It this case, the rich text box contains is now drawn in its entirety, i.e. it no longer has any scroll bars of its own. I still want the rich text box to be bound by the size of the page, i.e. if the browser is maximized and the rich text box contains 100s of lines of text, I can still see the border of the rich text box, and the rich text box will have scroll bars to allow viewing of its contenxt. When the browser window is smaller than the min size of the control, then I want scrollbars for the user control.
Is this possible?
Cheers
Just wrap a ScrollViewer around the "Client:UserControl1" on your page.
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<<Client:UserControl1 Margin="10"/>
</ScrollViewer>
Also remove all other references to ScrollViewer.HorizontalScrollBarVisibility and ScrollViewer.VerticalScrollBarVisibility.
Cheers

resize a WPF grid when window maximized to same portions as the window

i have a basic grid in my WPF application:
<Grid>
<Grid Height="260" HorizontalAlignment="Left" Margin="24,25,0,0" Name="grid1" VerticalAlignment="Top" Width="452">
<Border BorderBrush="Red" BorderThickness="6"></Border>
</Grid>
</Grid>
the grid is in the middle of the window.
When i maximize the window i want the grid to auto resize itself to the size of the window and stay with the same margin that i specified.
How do i do that ?
Do i have to calculate and resize the whole thing in the resize event?
i get from this:
to This (i dont want this):
i want the grid to resize to the same portions as it was , but for a full screen.
Remove Width and Height.
<Grid>
<Grid Margin="24,25">
<Border BorderBrush="Red" BorderThickness="6"></Border>
</Grid>
</Grid>
e: Added a second grid to make it identical to OP
You could host the Grid inside of another Grid with something like:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25" />
<ColumnDefinition />
<ColumnDefinition Width="25" />
</Grid.ColumnDefinitions>
<!-- Main Grid -->
<Grid Grid.Row="1" Grid.Column="1">
<!-- Main Content -->
</Grid>
</Grid>
That would allow you to put all your content inside of the Main Grid, while maintaining a constant margin of 25 around all edges.

WPF Element Binding With Dynamically Generated UI Elements

I have a page in which I have a grid with 2 columns, one accommodating 80* width and the other accommodating 20*. Beneath the grid is a stack panel to which I load UI elements (child stack panels) at runtime.
My objective is to bind the widths of the stackpanels to the columns of the grid. This works perfectly and the stackpenels resize if the dynamic content is mocked to be static in the design view. But when the application is run, the bindings fail and the widths are not bound.
Is there any way to refresh the bindings so that I can notify the stackpanels to refer the widths of the grid and configure its's size?
Updated:
This is what my XAML looks like:
<Page x:Class="WPFTestApp.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid x:Name="resizeGrid"
Grid.Column="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="leftColumn"
Width="80*" />
<ColumnDefinition x:Name="rightColumn"
Width="20*" />
</Grid.ColumnDefinitions>
</Grid>
<StackPanel x:Name="contentPanel"
Grid.Column="0" Grid.Row="0" >
<!-- Dynamic StackPanels are added here -->
</StackPanel>
</Grid>
</Page>
In my code, I create StackPanel elements and add it to the contentPanel by saying:
contentPanel.Children.Add(...);
Unfortunately, I HAVE to use StackPanels here. :-(
The markup of a dynamically created StackPanel element is as follows (note that I use a Binding to the grid already in the XAML):
<StackPanel x:Name="element01"
Orientation="Horizontal"
Width="{Binding ElementName=resizeGrid, Path=ActualWidth}" >
<StackPanel x:Name="leftPanel"
Orientation="Vertical"
Width="{Binding ElementName=leftColumn, Path=ActualWidth}">
<!-- Content goes here -->
</StackPanel>
<StackPanel x:Name="rightPanel"
Orientation="Vertical"
Width="{Binding ElementName=rightColumn, Path=ActualWidth}">
<!-- Content goes here -->
</StackPanel>
</StackPanel>
The XAML code for my dynamic StackPanel elements are generated through an XSLT transformation
Note the xmlns:x namespace dynamic StackPanel. This also has to be done because of it being generated through XSLT
As far as I know setting the Width of a StackPanel with Orientation="Horizontal" will have no effect. The size of a StackPanel does not exceed the size of its content in its oriented direction.
Why do you "HAVE" to use StackPanels here? You almost certainly want DockPanels, given your objective. You won't have to bind or set anything, because the DockPanel will fill the cell automatically.
Try binding the ActualWidth instead of Width.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid x:Name="resizeGrid"
Grid.Column="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="leftColumn"
Width="{Binding ElementName=contentPanel, Path=ActualWidth}" />
<ColumnDefinition x:Name="rightColumn"
Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<StackPanel x:Name="contentPanel"
Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" >
<StackPanel Background="Yellow" Width="100" Height="25" />
<StackPanel Background="Green" Width="120" Height="25" />
<StackPanel Background="Red" Width="140" Height="25" />
<TextBlock Background="Gray" Text="{Binding ElementName=contentPanel, Path=ActualWidth}" />
</StackPanel>
</Grid>
The following changes I have done above:
1) Set the leftColumn to the ActualWidth of the contentPanel
2) Set the rightColumn to *
3) contentPanel HorizontalAlignment should be changed other then Stretch. Here I have changed it to Left
HTH
I found a solution for this issue. (Sorry for the late response)
What I did was, I cut and pasted the "resizeGrid" Grid control into the "contentPanel" Stackpanel.
As I mentioned above, the contents within the contentPanel are generated through an XSLT transformation and this surely creates a namespace reference issue. I noticed "element not found..." message in the Output window whenever this Window is loaded - this proved me right.
Inserting the "resizeGrid" into the "contentPanel" helped because then both the controls are within the same namespace and can be referenced for a PropertyBinding using "ElementName" attribute.
Thank you for your support! :-)

WPF bug? Grid's column does not accommodate ListBox scrollbar

In the following example, the leftmost column's width does not increase to accommodate the ListBox's scrollbar that appears when the UserControl's height is decreased:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Example">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2">Example text</TextBlock>
<ListBox Grid.Row="1" Grid.Column="0">
<ListBoxItem>One</ListBoxItem>
<ListBoxItem>Two</ListBoxItem>
<ListBoxItem>Three</ListBoxItem>
<ListBoxItem>Four</ListBoxItem>
<ListBoxItem>Five</ListBoxItem>
</ListBox>
<Expander Grid.Row="1" Grid.Column="1" Header="Expander" />
</Grid>
</UserControl>
When the TextBlock with the ColumnSpan attribute is removed the column resizes as expected. Is this a bug in WPF?
It appears this is a known bug with the ListBox scrollbar and the WPF Grid. Microsoft also notes they will probably not have this fixed in 4.0.

Resources