Strange behavior of control position in wpf - c#

It's a strange behaviour about the WPF Control positioning. I had a below controls and aligned well during design time. However runtime gave the misaligned positioning in the corner of button
<Window x:Class="StackOverflow.LookAndWork"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Tables" Height="388" Width="314" ResizeMode="NoResize" >
<Grid>
<TextBox Margin="12,12,12,41"></TextBox>
<Button Content="OK" Height="23" Margin="205,314,12,12" Name="button3" Width="75" IsCancel="True" IsEnabled="False" />
</Grid>
</Window>
DesignTime Snap
Runtime Snap
Suppose If i removed the ResizeMode="NoResize" from the Window. I can able to see the correct positioning at runtime. What is the problem with ResizeMode="NoResize" ?
Anyhelp would be greatly appreciated !!!

Instead of adding the margin in control level, why don't you add the minimum margin in grid level?
Example:
<Grid Margin="12,12,12,12">
This way you will get a 12 pixel margin border.
On the button, don't do hardcoded left margin. Instead, you can use HorizontalAlignment="Right" to do the job.
On a side note, I less prefer to add controls in grid without specifying the Grid.RowDefinitions, Grid.ColumnDefinitions, Grid.Row and Grid.Column. It is a poweful tool for Grid.

For better looking, don't use Margin or Size. Use Grid definition to split your application.
With the following xaml, your application will always have a good looking :
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="23" />
</Grid.RowDefinitions>
<TextBox />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Content="OK" Name="button3" IsCancel="True" IsEnabled="False" />
</Grid>
</Grid>
Width and Height can be define in a Dictionary. In this case, in RowDefinition and ColumnDefinition properties, use Auto instead of values.
Edit :
Use a Dictionnary like
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="75"/>
<Setter Property="Height" Value="23"/>
</Style>
</ResourceDictionary>
then
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Content="OK" Name="button3" IsCancel="True" IsEnabled="False" />
</Grid>
</Grid>

I can't see the same issue in VisualStudio 2012 designer: http://screencast.com/t/TGVgUyfR
Both design-time and runtime are look the same. So there should be a bug in a prior version of the designer.
Nevertheless I'd suggest you to move your button into separate grid row or use another layout controls to organise your views.

To extend Xaruth's answer, I'd not fix the height for the button row, but instead have it use the default height. The same goes for the width, which I'd have the button define.
Also note that I give the button a margin. The added bonus of not fixing the grid column/row sizes it that now the row height also takes the margin into account:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Content="OK" Name="button3" IsCancel="True" IsEnabled="False" Width="75" Margin="0,8,0,0" />
</Grid>
</Grid>

Related

How to make Responsive Grid using Avalonia framework

I want to make responsive desktop application which can run on different screen size as well as different platform.
I have used Grid.Extra.Avalonia library but it is only working for border.
I want to make grid Which have 2X2 column and row within that column and row we can place other control which would be responsive based on scree size.
Below is my code.
<Window
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ge="clr-namespace:GridExtra.Avalonia;assembly=GridExtra.Avalonia"
x:Class="ResponsiveGridSample.MainWindow"
Title="ResponsiveGrid Example" Height="350" Width="525">
<Grid>
<Grid.Styles>
<Style Selector="Grid">
<Setter Property="ge:ResponsiveGrid.XS" Value="12" />
<Setter Property="ge:ResponsiveGrid.SM" Value="6" />
<Setter Property="ge:ResponsiveGrid.MD" Value="2" />
</Style>
</Grid.Styles>
<ge:ResponsiveGrid>
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<!--<Label Grid.Column="0" Grid.Row="0">Vehilce Class</Label>-->
<ComboBox Grid.Column="1" Grid.Row="0" Width="250">
<ComboBoxItem>Car</ComboBoxItem>
<ComboBoxItem>Jeep</ComboBoxItem>
<ComboBoxItem>Van</ComboBoxItem>
</ComboBox>
</Grid>
</ge:ResponsiveGrid>
</Grid>
</Window>```
Where can we add class selector for grid to make responsive.

WPF - Why are buttons resizing after busy indicator goes away?

When the busy indicator is visible the buttons resize to a wider width and when the indicator goes away it resizes back down to expected width. I thought using span attribute would fix this but it didn't.
<Window x:Class="TelerikWpfApp3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
Title="MainWindow" Height="350" Width="525" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<telerik:RadBusyIndicator x:Name="LogonBusyIndicator" IsBusy="True" Grid.ColumnSpan="3" Grid.RowSpan="3">
<StackPanel>
<Button x:Name="button1" Content="Button 1" Grid.Column="0" Grid.Row="0" Margin="20" Padding="10" />
<Button x:Name="button2" Content="Button 2" Grid.Column="1" Grid.Row="0" Margin="20" Padding="10" Click="button2_Click"/>
</StackPanel>
</telerik:RadBusyIndicator>
</Grid>
</Window>
Set the Content of the RadBusyIndicator to the Grid with the buttons:
<telerik:RadBusyIndicator x:Name="LogonBusyIndicator" IsBusy="True" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Button x:Name="button1" Content="Button 1" Grid.Row="0" Margin="20" Padding="10" />
<Button x:Name="button2" Content="Button 2" Grid.Row="1" Margin="20" Padding="10" Click="button2_Click"/>
</Grid>
</telerik:RadBusyIndicator>
What action causes the busy indicator to disappear? Are you programmatically setting IsBusy to False in code-behind once login is ready? If you don't want Button1 and Button2 to be clicked before the busy indicator closes, you can always do a trigger like this.
<StackPanel>
<Button x:Name="button1" Content="Button 1" Grid.Column="0" Grid.Row="0" Margin="20" Padding="10" />
<Button x:Name="button2" Content="Button 2" Grid.Column="1" Grid.Row="0" Margin="20" Padding="10" Click="button2_Click"/>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="IsHitTestVisible" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBusy, ElementName=LogonBusyIndicator}" Value="False">
<Setter Property="IsHitTestVisible" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<telerik:RadBusyIndicator x:Name="LogonBusyIndicator" IsBusy="True"/>
Here's what's happening with the code above.
First and foremost, by removing the buttons entirely from the telerik RadBusyIndicator xaml definition, the buttons size will remain their original size and not get resized whenever the busy indicator turns off or on. I think by placing these buttons inside of the RadBusyIndicator, you have put a reliance on how that telerik control sizes itself. Now there should be no dependency.
The busy indicator will ALWAYS be placed above the buttons in the visual tree z-order, because I defined it last.
To prevent the user from clicking the buttons until the busy indicator is ready, I have set the IsHitTestVisible to false by default. This means that anything in the StackPanel cannot be clicked.
But then I set up a trigger to say, when the busy indicator's "IsBusy" property gets set to False (programmatically?), then set the StackPanel's IsHitTestVisible property to True so that the user can now click these buttons.

UWP XAML: Filling the screen with 2 elements, one Viewbox

I have a grid with two elements, a scaling Viewbox and a Textblock. I want to have the Viewbox take only the space it needs, but also only the space it can get.
Images explain it much better, the desired image first:
However, when I resize my application to be wider, the Viewbox starts to overtake the Textblock below it:
Here's a dumbed down version of my XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="MainGrid" Margin="0" UseLayoutRounding="False">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0" />
</Grid.ColumnDefinitions>
<Viewbox Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Row="0" x:Name="Zulrah">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Fill="Blue" Width="150" Height="250" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<Rectangle Grid.Column="1" Fill="Red" Width="150" Height="250" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</Grid>
</Viewbox>
<TextBlock Grid.Row="1" x:Name="TextOutput" MinHeight="100" MinWidth="100">
Hello world!
<LineBreak />
Life's good
</TextBlock>
</Grid>
You can more or less ignore the second column (with Width="0"), it's used for when the application becomes wide-screen (or landscape). It has the same issue:
In short: I want the TextBlock to obey it's MinHeight="100", while still maximizing the space the Viewbox uses.
PS: Please note that some settings make the Viewbox scale to a larger size than actually fits on the screen, this is not desireable!
Edit: Remarkably, setting a MinHeight="100" on the second row has no effect...
Since you are using ThemeResource in your code, I think you are developing an UWP app as there is no ThemeResource in WPF. If so, please remove WPF in your title and tags as they are two different frameworks. Mixed use of UWP and WPF may cause confusion.
For UWP apps, in Grid, while setting row's height to Auto, the row will size to fit its content. After the Auto rows are calculated, the row which height is set to * will get part of the remaining height.
According to your description, you want the TextBlock to obey it's MinHeight and the Viewbox gets part of the remaining height. So you can change the RowDefinitions like following:
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
And to make the Viewbox fill the remaining area, we can set VerticalAlignment and HorizontalAlignment to Stretch. Besides this, you may also need to set Stretch property to Fill to make the content in Viewbox resize to fill the destination dimensions.
The complete XAML code may like following:
<Grid x:Name="MainGrid"
Margin="0"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
UseLayoutRounding="False">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0" />
</Grid.ColumnDefinitions>
<Viewbox x:Name="Zulrah"
Grid.Row="0"
AllowDrop="True"
Stretch="Fill">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0"
Width="150"
Height="250"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Blue" />
<Rectangle Grid.Column="1"
Width="150"
Height="250"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Red" />
</Grid>
</Viewbox>
<TextBlock x:Name="TextOutput"
Grid.Row="1"
MinWidth="100"
MinHeight="100">
Hello world!
<LineBreak />
Life's good
</TextBlock>
</Grid>

How to stop Listbox from growing on screen as new items are inserted

My WPF application has a window that contains a ListBox. For some reason that I don't understand, it started growing on screen today after items are inserted into it. I want its height to stay fixed and I don't want it to grow every time an item is inserted.
Here's the XAML for the window:
<Viewbox Stretch="Uniform">
<Grid Background="{DynamicResource WindowBackground}"
Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="{DynamicResource AlarmTitleBackground}"
Grid.Row="0"
MouseLeftButtonDown="LeftMouseButtonDown">
. . .
</Grid>
<Rectangle Fill="{DynamicResource AlarmTitleBackground}"
Grid.Row="1"
Height="4" />
<Grid Background="{DynamicResource ControlBackground}"
Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid FocusManager.IsFocusScope="True"
Grid.Column="0"
Grid.Row="0"
Name="PendingAlarmScope">
<ListBox Background="{DynamicResource TextBackground}"
HorizontalContentAlignment="Center"
IsSynchronizedWithCurrentItem="True"
Margin="5"
MinWidth="185"
VerticalAlignment="Stretch"
Name="AlarmsList"
SelectionChanged="AlarmsList_SelectionChanged" />
</Grid>
. . .
</Grid>
</Grid>
</Viewbox>
I found a post in a blog about a TextBox that kept growing as characters were typed. The author indicated that the TextBox was in a ScrollViewer with the HorizontalScrollBarVisibility property set to "Auto". They changed it to "Disabled" and this fixed it for them. I tried adding ScrollViewer.VerticalScrollBarVisiblility="Disabled" to the xaml but this didn't work. I also tried binding theListBox's MaxHeight property to theActualHeight` of another control that's the same exact height as I want & that didn't work, either.
How do I fix the Height of the ListBox without setting it? I want the ListBox to always fill the Grid cell it's in, and the window to grow and rescale itself for different screen resolutions.
<Grid Background="{DynamicResource ControlBackground}"
Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
for grins would you try dropping the view box and some other stuff
<Grid Background="{DynamicResource WindowBackground}"
Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Fill="{DynamicResource AlarmTitleBackground}"
Grid.Row="1"
Height="4" />
<ListBox Grid.Row="2" Background="{DynamicResource TextBackground}"
HorizontalContentAlignment="Center"
IsSynchronizedWithCurrentItem="True"
Margin="5"
MinWidth="185"
VerticalAlignment="Stretch"
Name="AlarmsList"
SelectionChanged="AlarmsList_SelectionChanged" />
</Grid>
After many hours of trying numerous things, I finally bit the bullet & set the Height of the ListBox to a value that I found using Snoop before it started growing. This stopped it from growing every time a new item was inserted. It was the only thing I could find to do that worked. A very frustrating day.

WPF - Expander in Grid - eating space

I have very simple xaml.
<Grid Margin="0,50,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<!--<RowDefinition Height="50"/>-->
</Grid.RowDefinitions>
<Expander Header=""
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
ExpandDirection="Right"
IsExpanded="True"
Grid.Column="0"
Grid.Row="0"
Height="Auto"
>
<!-- My List control -->
</Expander>
<TabControl Name="ExecutionTab" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch">
<!-- soem tabs here -->
</TabControl>
</Grid>
Now after collasping expander the left part [row=0,col=0] being shown as empty with space.
What we want is right part [row=0,col=1] should take whole space.
What should be done in this case ?
I have tried HorizontalAlignment="Stretch" to Tab control but not working.
Do I need to add event handler like on collapse and change width of grid.. but it does not seems to good way ?
Can anyone suggest better way ?
Thanks
Using a Grid is not the best way to achieve what you want. You should use a DockPanel instead with LastChildFill = "true". I can't try it now but I would imagine it like this:
<DockPanel LastChildFill="true">
<Expander Header=""
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
ExpandDirection="Right"
IsExpanded="True"
DockPanel.Dock="Left"
Height="Auto"
>
<!-- My List control -->
</Expander>
<TabControl Name="ExecutionTab" HorizontalAlignment="Stretch">
<!-- soem tabs here -->
</TabControl>
</DockPanel>
This should make the tab control always take the entire remaining space.
You can make this work by setting your column definitions to:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
The complete code to show this working is below:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Expander ExpandDirection="Right" IsExpanded="True">
<TextBlock FontSize="50">Text For Expander</TextBlock>
</Expander>
<TabControl Name="ExecutionTab" Grid.Column="1">
<TabItem Header="Tab 1">
<TextBox FontSize="50" TextWrapping="Wrap">Text for Tab 1</TextBox>
</TabItem>
<TabItem Header="Tab 2">
<TextBox FontSize="50" TextWrapping="Wrap">Text for Tab 1</TextBox>
</TabItem>
</TabControl>
</Grid>
If you add the xaml above to a window, you should see the following
You will have to make you ColumnDefinition.Width to Auto and if you want fixed width for your TabControl you should give Width to TabControl.
<Grid Margin="0,50,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>

Categories

Resources