Why this window is a mess? [closed] - wpf

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
111
XAML:
<Window x:Class="WPFApp.Root"
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:WPFApp"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="Root" Height="454" Width="392">
<Grid>
<ListBox Margin="10,10,10,57"/>
<Button HorizontalAlignment="Left"
Margin="10,386,0,0"
VerticalAlignment="Top"
Height="42" Width="185"
Content="TEST BUTTON">
</Button>
</Grid>
</Window>

You're using a Grid, but you're not positioning things using the Grid. Your Grid needs to have ColumnDefinitions and/or RowDefinitions, and in the items in the Grid, you need to specify the Grid.Column and/or Grid.Row they're in.
If your UI can be as simple as the above, though, consider using a simpler container such as the DockPanel. You can set your Button to be positioned at DockPanel.Dock="Bottom" and then your ListBox can fill the remaining space in the DockPanel.
Have a look here for more details, and sample markup, of how to use the Grid and DockPanel:
Grid
DockPanel

The Window height (450) is too small to vertically fit all of the content. To avoid using large fixed margins or offset positions, which will easily mess up when the parent window is resized, you can use a lot of the WPF auto-sizing features. For example You can add two rows to host the button and the listbox and you will have a more flexible view:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Margin="10" Grid.Row="0"/>
<Button HorizontalAlignment="Left" Grid.Row="1"
Margin="10"
VerticalAlignment="Top"
Height="42" Width="185"
Content="TEST BUTTON">
</Button>
</Grid>

Related

How can we show UWP user control on vertical-top edge of the parent window?

Following XAML in this Microsoft tutorial is showing too much gap between the top edge of the parent window and the UWP user control. Question: How can we make the user control align to the top edge of parent window? Remark: The VerticalAlignment="Top" in the StackPanel below does not help. This question is something similar to this post but in a different context.
<UserControl
x:Class="ClassLibUWP_inside_WPF.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ClassLibUWP_inside_WPF"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
d:DesignWidth="400" Height="329">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="211*"/>
<ColumnDefinition Width="189*"/>
</Grid.ColumnDefinitions>
<StackPanel Background="LightCoral" Grid.ColumnSpan="2">
<TextBlock>This is a simple custom UWP control</TextBlock>
<Rectangle Fill="Blue" Height="93" Width="100"/>
<TextBlock Text="{x:Bind XamlIslandMessage}" FontSize="50"></TextBlock>
<winui:RatingControl Height="32" />
</StackPanel>
</Grid>
</UserControl>
When you run the app built in the above tutorial, you get the following screen showing the above UWP user control:
I would instead like to display it as follows [notice about no gap between window title and the red stack panel]:
The UserControl has a fixed height that is smaller than the height of the window and thus is vertically centered in the window. Setting VerticalAlignment="Top" on the WindowsXamlHost should give what you want.

Opening new UserControl in MainWindow erases all empty rows

Once I run the program, it opens a UserControl in my MainWindow. The UserControl is a Menu consisting of 3 buttons.
Image of the UserControl:
Menu
The code behind Main Window:
<Window
...
Title="MainWindow" Height="350" Width="525" SizeToContent="WidthAndHeight" >
<Window.DataContext>
<ViewModels:MainWindowViewModel />
</Window.DataContext>
<ContentControl Content="{Binding CurrentViewModel}"/> //Inserts a UserControl
The code behind Menu UserControl:
<UserControl
...
d:DesignHeight="90" d:DesignWidth="525" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*"/> //Problem
<RowDefinition Height="100*"/>
<RowDefinition Height="100*"/> //Problem
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Row="1" Margin="30,0" Content="First" Command="{Binding DataContext.SwitchToNextUserControl,
RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}, Mode=OneWay}" />
<Button Grid.Row="1" Grid.Column="1" Margin="30,0" Content="Second"/>
<Button Grid.Row="1" Grid.Column="2" Margin="30,0" Content="Third"/>
</Grid>
THE PROBLEM:
Once the menu is opened, the empty rows (those without buttons, first and third) get collapsed (or just height to 0?), as shown: Running program
I can get over it with setting MinHeight for every row, but it works only on pixels. I'd like them to work in the method of stars ("*"). I guess I could set their height from code behind (using stars), but just the thought of it makes me feel like I rub my right ear with left hand.
Also, once I click on the "First" button, some other UserControl is opened in the window, instead of the "Menu" one, and its rows are also collapsed. Just mentioning it.
So the question is, what should I do to make my UserControls appear just as they look in designer?
You should remove to SizeToContent="WidthAndHeight" from your window XAML.
This causes the height of the window to shrink to fit the size of the UserControl (and effectively the height of the middle Button).

WPF: Two borders with solid background have a ugly pixel row on top (merging color with parent panel's background)

Below there is shown a simple part of my wpf app where you can see two borders (1. and 2.).
At 3. you can see a lite red line (which is my problem). This line was never (explicitly) defined in xaml code. The red background was only defined in a parental grid and is gleam through at the top of the border element. Below Is my code:
<Window
x:Class="BgColorBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="200"
WindowStartupLocation="CenterScreen"
>
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="1" Background="Red">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Border
Grid.Row="0"
Height="4" Background="#1F1F1F" />
<Border
Grid.Row="1"
Background="#777777"
>
<WrapPanel
Orientation="Horizontal"
HorizontalAlignment="Right"
>
<Button Padding="7" Margin="7">Hello</Button>
<Button Padding="7" Margin="7">World</Button>
</WrapPanel>
</Border>
</Grid>
</Grid>
When I define fix row heights (instead of the auto value) then the red line is not showing so I think it's a rendering problem (by the side the border from 1. has a red line too).
While I has written my question I found that article with the solution to my problem.
There must be declared UseLayoutRounding="True" on any grid above the last one (because that value is inherited down).
<Grid Grid.Row="1" Background="Red" UseLayoutRounding="True">
After known the keyword 'LayoutRounding' I found this Article on StackOverflow with a similar problem.
After knowing the issue with LayoutRounding=False I don't know what are the benefits from not using it? Maybee performance?
What is the best practise using that flag? In some Microsoft articles they say to set it true on the root element (which is the main window). But if so then I'm wondering why that flag is not true by default.

Windows Forms UserControls hosted in WPF spilling over side of window

I'm converting an old WinForms app to WPF. To speed the migration, I'd like to host as many of the old app's UserControls as possible in WindowsFormsHost elements.
When I do, however, the controls seem to spill over the side of the window! It's as if the hosted control believes the window is about 20% wider than it actually is.
To illustrate what I mean, here's a shot of the WinForms control in the designer:
And here's a shot of the control once it's hosted in the app:
Has anyone else seen this before? What is this caused by, and how do I fix it?
The WindowsFormsHost element is inside a TabControl's TabItem, if that makes any difference.
Edit: Here is the relevant XML:
<Window x:Class="MyWPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:forms="clr-namespace:MyWinFormsApp;assembly=MyWinFormsApp"
Title="MainWindow" Height="600" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- Grid Row 1 -->
<!-- Other controls here in row 1 -->
<!-- Grid Row 2 -->
<TabControl Grid.Row="2">
<TabItem Header="Advanced">
<WindowsFormsHost>
<forms:BinaryCommandControl/>
</WindowsFormsHost>
</TabItem>
<TabItem Header="Options">
<WindowsFormsHost>
<forms:OptionsControl/>
</WindowsFormsHost>
</TabItem>
</TabControl>
</Grid>
</Window>
BinaryCommandControl and OptionsControl are both custom WinForms UserControl elements.

WPF TabControl Children

This is my current Scenario: I have several UserControls inside different TabItems on a single TabControl in a WPF Window. Something Like:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="S.C.A.R" WindowState="Maximized">
<TabControl Name="MainTabControl">
<TabItem Name="TabOps">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Local:ServiceList Height="Auto" CanInsert="True" CanCollapse="True" Grid.ColumnSpan="3" x:Name="SL" RecordState="Edit"/>
<Local:ReservationList CanCollapse="True" Grid.Row="1" RecordState="Edit" x:Name="RL"/>
<Local:DriverList CanDelete="False" CanInsert="False" CanCollapse="True" Grid.Row="1" Grid.Column="2" RecordState="Edit" x:Name="DL"/>
<Local:CustomerForm CanDelete="False" CanInsert="False" Grid.Row="2" Grid.ColumnSpan="3" RecordState="View" x:Name="CL"/>
</Grid>
</TabItem>
<TabItemItem Name="TabCodes">
<Local:CustomerList x:Name="CustomerCRUD" RecordState="View"/>
</TabItem>
<Button Grid.Row="1" Content="TEST" Click="Button_Click"/>
</Grid>
</Border>
</Window>
Sorry for the indentation. For some reason I can't get the code properly indented here :(
What I need to do is to determine (preferably in the TabControl.Load Method, which of my different UserControls are currently visible. I need to do this in a dynamic way, I cannot hardcode the relationship between the TabItems and their children, something like:
if (TabControl.SelectedItem is XXXX)... is not possible here, because this is a Dynamic UI and I have no way to know which controls are there up front.
I've been digging a little bit and found out that the TabItem controls do not appear in the Visual tree of their "children". I only see a ContentPresenter, and then the TabControl itself. It looks like the tabItems do not "contain" their own content, so I could not, for example, do a FindAncestor to the Tab Items.
Another interesting fact is that the Loaded event of my usercontrols is being called on startup. Regardless of whether or not they're visible on screen.
An ideal scenario will be to find an event that is only fired on my Usercontrols when the TabItem they are under gets selected.
Appreciate any ideas. Thanks in advance
You should be able to leverage the VisualTreeHelper and consequentrly this answer on SO to provide the TabItem.Content returned object and look for the your specified type, UserControl in this instance.
NOTE:
For additional details please see the comments which transpired in the SO's question.

Resources