Margin for Two Boxes Isn't Correct - c#

so I have two boxes, and the goal here is to have both boxes have the exact same margins from the edge of the window. Unfortunately, in WPF, you only get the margin from the left side, and not both, so to make sure of that, I have the following formula;
The margin of the second box is equal to the window width minus the margin of the first box minus the size of the box.
And this can be backed up with math, it does work. And so I did get my program to figure this out, since it's reactive. And so now I have this image:
WPF Window
The text in the middle is to prove that this calculation is correct. (just so you know, each box is 500px wide) So, the first number is the margin of the first box. The second is the margin of the second, and the last is the window size. Do the math and you have this equation:
(1936 - 88) - 500 = 1348
And that does work, however, if you look in the image, the box on the right is just a little bit closer to the edge than the one on the left. This happens too if you resize it, it's not just when maximized. What's up, and how can I fix this?
Here is my XAML code:
<Window x:Class="Horizon_Chat.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:Horizon_Chat"
xmlns:i="clr-namespace:Horizon_Chat"
i:WindowEx.ShowIcon = "false"
mc:Ignorable="d"
Title="Horizon Chat" Height="900" Width="1280" WindowStartupLocation="CenterScreen" MinWidth="600" MinHeight="600" WindowState="Maximized">
<Grid>
<TextBlock x:Name="welcomeTitleText" HorizontalAlignment="Center" Margin="0,-200,0,0" TextWrapping="Wrap" Text="Hello Camden!" VerticalAlignment="Center" FontFamily="Muli" FontSize="60"/>
<Border x:Name="topBorder" BorderBrush="#FF646464" BorderThickness="0,0,0,4" HorizontalAlignment="Left" Height="41" VerticalAlignment="Top" Width="1273" Margin="0,32,0,0"/>
<Ellipse Fill="#FF30B44E" HorizontalAlignment="Left" Height="50" Margin="10,10,0,0" Stroke="Black" VerticalAlignment="Top" Width="50" StrokeThickness="3"/>
<Border x:Name="chatsBox" BorderBrush="Black" BorderThickness="3" HorizontalAlignment="Left" Height="250" Margin="58,594,0,0" VerticalAlignment="Top" Width="500"/>
<Border x:Name="friendsBox" BorderBrush="Black" BorderThickness="3" HorizontalAlignment="Left" Height="250" Margin="724,594,0,0" VerticalAlignment="Top" Width="500"/>
</Grid>
</Window>

What you're looking for is a grid, set the ColumnDefinition Widths to your rectangle width + the margin you want. The * used for the middle Column's Width means "Fill up the available space". The Margin parameter is set up as (Left, Top, Right, Bottom). This allows you to specify a right hand Margin.
<Window x:Class="ForStackoverflow.MainWindow"
...
xmlns:local="clr-namespace:ForStackoverflow"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Rectangle Margin="15 0 0 0"
StrokeThickness="5"
Stroke="Black"
Height="80"
Grid.Column="0"/>
<Rectangle Margin="0 0 15 0"
StrokeThickness="5"
Stroke="Black"
Height="80"
Grid.Column="2"/>
</Grid>
</Window>

Related

center label inside rectangle with dynamic width

I have a Window with a canvas that has a rectangle at the top of it. It will stretch to fill the width if the canvas. The Canvas is set to be maximized with no toolbar to fill the entire screen like so:
<Window x:Class="Ericsson.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:Ericsson"
mc:Ignorable="d"
Title="MainWindow" WindowStyle="None"
WindowState="Maximized">
<Window.Resources>
<SolidColorBrush x:Key = "brushResource" Color = "Black" />
</Window.Resources>
<Canvas x:Name="MyCanvas" >
<Rectangle x:Name="TopRect" Fill="Black" Height="120" Canvas.Top="0" Canvas.Left="0" Width="{Binding ElementName=MyCanvas, Path=ActualWidth}"/>
<Label Content="Welcome to My World" Foreground="#FFFFFF" FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Canvas>
</Window>
My problem is this, I have a label that needs to be centered inside of the dynamic rectangle. The XAML code above puts the label in the upper left hand corner. So "HorizontalAlignment" and "VerticalAlignment" didn't work.
How do I center the label both horizontally and vertically inside of my rectangle?
Thanks
you can introduce an additional container - Grid - which will align elements properly:
<Canvas x:Name="MyCanvas">
<Grid Width="{Binding ElementName=MyCanvas, Path=ActualWidth}">
<Rectangle x:Name="TopRect" Fill="Black" Height="120" />
<Label Content="Welcome to My World" Foreground="#FFFFFF" FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Canvas>

Scaling the elements within a WPF application across different screen sizes

I am trying to create an full-screen WPF application that is scales across a number of screen sizes. However, what I've found is that the window elements do not scale and position themselves correctly when the program in different screen sizes.
i.e. in VS2013
i.e. when run
How would I get the program to scale accordingly? For instance, I would like the buttons to be positioned to the either the left or right of the screen and the listbox to scale up to fill up the screen.
This is my code so far:
<Window x:Class="FYP.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" WindowStartupLocation="CenterScreen" WindowState="Maximized">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Button Content="View Messages" Grid.Column="1" HorizontalAlignment="Left" Margin="203,20,0,0" VerticalAlignment="Top" Width="97" Name="ViewMessagesButton"/>
<Button Content="Log Out" Grid.Column="1" HorizontalAlignment="Left" Margin="305,20,0,0" VerticalAlignment="Top" Width="65" Name="LogOutButton"/>
<TextBlock HorizontalAlignment="Left" Margin="20,20,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="20" Name="DateTimeTextBlock"/>
<ListBox HorizontalAlignment="Left" Height="434" Margin="20,60,0,0" VerticalAlignment="Top" Width="350"/>
<ListBox HorizontalAlignment="Left" Height="135" Margin="20,60,0,0" VerticalAlignment="Top" Width="350" Grid.Column="1"/>
<ListBox HorizontalAlignment="Left" Height="278" Margin="20,216,0,0" VerticalAlignment="Top" Width="350" Grid.Column="1"/>
</Grid>
</Window>
If you really want the objects to scale up or down (as opposed to resizing), and you want the aspect ratio of your arrangement to remain the way you arranged it initially, you should be using WPF's ViewBox control.
Your problem is that you have set concrete sizes to all of you controls. Remove the width and height on your controls and set the margin the way you want.
Remove the width and heights, and set the horizontal and vertical alignments to stretch.

WPF : Transparency of Window eliminated by semi-transparent brush of a contained object

I have a Window with the property AllowsTransparency set to true, and with the Background property set to a semi-transparent color, the code :
<Window x:Class="InstantSnip.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Main, Source={StaticResource Locator}}"
AllowsTransparency="True"
WindowStyle="None"
ResizeMode="NoResize"
Topmost="True"
Width="180" Height="80"
Background="#7FFFFFFF" >
<Border x:Name="LayoutRoot"
BorderBrush="#99FFFFFF"
BorderThickness="1"
CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource NewSnipButton}" Margin="5,0"/>
<Button Grid.Column="1" Style="{StaticResource ReTrySnippingButton}" Margin="5,0"/>
<Button Grid.Column="2" Style="{StaticResource CloseButton}" Margin="5,0"/>
</Grid>
</Border>
</Window>
This is how it looks like :
Now, I want to give the Background="#7FFFFFFF" to the LayoutRoot Border instead of the Window so that the color can fit exactly and only inside the Border's boder, which is not the case when the Background="#7FFFFFFF" is a property of the Window as you can see here :
And hence, and with no big changes, the code will simply be as follows :
<Window x:Class="InstantSnip.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Main, Source={StaticResource Locator}}"
AllowsTransparency="True"
WindowStyle="None"
ResizeMode="NoResize"
Topmost="True"
Width="180"
Height="80">
<Border x:Name="LayoutRoot"
BorderBrush="#99FFFFFF"
Background="#7FFFFFFF"
BorderThickness="1"
CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource NewSnipButton}" Margin="5,0"/>
<Button Grid.Column="1" Style="{StaticResource ReTrySnippingButton}" Margin="5,0"/>
<Button Grid.Column="2" Style="{StaticResource CloseButton}" Margin="5,0"/>
</Grid>
</Border>
</Window>
But what I get is this :
My first question is, why ?
My second question is, can you suggest a solution for this problem.
Set Background to Transparent in your Window that will do the trick
eg
<Window x:Class="InstantSnip.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Main, Source={StaticResource Locator}}"
AllowsTransparency="True"
WindowStyle="None"
ResizeMode="NoResize"
Topmost="True"
Width="180"
Height="80"
Background="Transparent" >
result
I don't have your styles so the button appears normal button
Edit
Explanation for your first question
As the default Background of a Window is usually White inherited from SystemColors.WindowColor. So unless you set any color which is fully or partially transparent, AllowsTransparency will not be able to compose transparency on it's own.
as any child control is rendered on window first then the whole window is composed to the background. So in short no matter what transparent color you set on your child controls it will be composed on a white background leading to no transparency.
so set Transparent on Window and then you can choose to have rounded corner border etc with desired transparent color.
From: Transparent Windows in WPF
WPF can obviously render transparent elements within its own window, but it also supports rendering the entire window with per-pixel transparency. This feature comes with a few issues.
If I'm reading your code correctly, you moved the Background property from the window to the border control. My guess, and it's only a guess, is that UserControls don't support transparent backgrounds.
This sounds similar to AllowTransparency alternative for rounded edge forms. Perhaps its accepted answer will work for you.

how do i get my datagrid to grow with the window and maintain margins?

Everything about my layout will flow with the resizing of the main window. The problem I'm facing is that as you can see, the datagrid goes off the screen. If you maximize the window, the datagrid will resize with the window, but continue to go off the screen. How do I get it to maintain its margin of 20 with it's parent grid?
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Height="170" Name="txtSQL" VerticalAlignment="Top" AcceptsReturn="True" TextWrapping="Wrap" Margin="20"/>
<Button Content="Run!" Height="23" HorizontalAlignment="Left" Name="btnRun" VerticalAlignment="Top" Margin="20,0,0,0" Width="75" Click="btnRun_Click" />
<Grid>
<my:DataGrid Name="dgResults" VerticalAlignment="Top" Margin="20" />
</Grid>
</StackPanel>
</Grid>
UPDATE:
Just to be more specific. The effect I'm trying to accomplish here is this:
When the window first loads, you are presented with a blank datagrid, so it's only about 15 pixels high. When you run the query, it will populate the datagrid by reassigning the itemssource. As of now, when you do that, if the data exceeds the window size, it will go off the bottom of the screen. I need it to only expand to the bottom of the window then enable the scrollbar. I can do this just by wrapping it in a scrollviewer im sure. However, when the window is resized, the datagrid needs to resize with it.
I'm wondering if the setup might have something to do with it. The form is actually a wpf page being displayed in a frame.
UPDATE:
<Page x:Class="Hold_Database___Prototype_1.Views.SQL"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="304" d:DesignWidth="732"
Title="SQL" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit" AllowDrop="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="23" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Height="170" Name="txtSQL" VerticalAlignment="Top" AcceptsReturn="True" TextWrapping="Wrap" Margin="20" Grid.Row="0"/>
<Button Content="Run!" Height="23" HorizontalAlignment="Left" Name="btnRun" VerticalAlignment="Top"
Margin="20,0,0,0" Width="75" Grid.Row="1" Click="btnRun_Click" />
<DockPanel Grid.Row="2">
<my:DataGrid Name="dgResults" Margin="20" />
</DockPanel>
</Grid>
</Page>
What is the dock panel for in this example?
Try putting the DataGrid directly in the cell with no stackpanel. If you are setting the button height then set set grid to auto.
Also, why give so much space to the text?
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Height="170" Name="txtSQL" VerticalAlignment="Top" AcceptsReturn="True" TextWrapping="Wrap" Margin="20" Grid.Row="0"/>
<Button Content="Run!" Height="23" HorizontalAlignment="Left" Name="btnRun" VerticalAlignment="Top"
Margin="20,0,0,0" Width="75" Grid.Row="1" Click="btnRun_Click" />
<my:DataGrid Grid.Row="2" <my:DataGrid Name="dgResults" Margin="20" />
Then also set HorizontalAlignment, VerticleAlignment, HorizontalContentAlignment, and VerticalContentAlignment = stretch
Your Grid is drawn off screen without a scroll bar because you are using a StackPanel. Care must be taken when using StackPanel - it is the most simplistic of all WPF Panel derived classes since its MeasureOverride calls Measure for all of its children with a size of double.PositiveInifity regardless of how much space the panel actually has available. Even a ScrollViewer will not help you with a StackPanel (the ScrollBar will be shown, but you won't be able to move it).
For example, consider a Window 350 in height and width, and a single Button as its content which is 500 in both height and width:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="350">
<StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Button Content="Hello" Height="500" Width="500" />
</ScrollViewer>
</StackPanel>
</Window>
Similar to your example, the Button here is drawn off screen in both the vertical and horizontal directions and a non-functional scroll bar will be present. If we change the panel to one which respects the size of its given area (e.g. DockPanel):
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<ScrollViewer>
<Button Content="Hello" Height="500" />
</ScrollViewer>
</DockPanel>
</Window>
then scroll bars appear which are functional and hence allow the content off screen to be shown by scrolling.
Hope this helps!
What I have done was do define the horizontal and vertical alignments to "Stretch" respectively at the control you want (your DataGrid) to take up the size based on the window being resized.

Centering a large rectangle inside a grid which dimensions are smaller (and ClipToBounds doesn't work)

I'm trying to position a rectangle in the center of a grid with a restricted height, like so:
<Grid ClipToBounds="False">
<Grid Background="LightBlue" Height="10" ClipToBounds="False" Margin="0,27,0,79">
<Rectangle Height="40" Width="20" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" ClipToBounds="False"/>
</Grid>
</Grid>
I've expected it to look like that:
But instead it looks like that:
I know the my child rectangle is bigger and it is understandable that it clips, however, my ClipToBounds have no effect of anything. After reading around, I found that indeed Grid does not respect "ClipToBounds".
I tried to use Canvas, as suggested in the aforementioned article by Dr.Wpf but I can't seem to get it right.
Is there anything I can do to make it look like the 1st picture, without resorting to C# code?
Thanks!
It's a little hard to tell exactly what your requirements are here. You said you tried it witha Canvas, but you can't seem to get it right. What didn't work?
I used this code:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TestApp.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="175" Height="170" Background="LightGray">
<Grid>
<Canvas Background="LightBlue" Height="10"
Margin="0,27,0,79" VerticalAlignment="Top">
<Rectangle Height="40" Width="20" Fill="Black"
Canvas.Left="66" Canvas.Top="-15" />
</Canvas>
</Grid>
</Window>
and was able to essentially fake what your screenshot looked like. But (as you can tell by the Canvas.Left and Canvas.Top parts of my code) it is sort of hackish. You could get rid of the Canvas.Left by binding to the ActualWidth of the Canvas and using an IValueConverter that converts it to the correct value.
Edit:
After a little further exploration, I came up with a slightly less hackish way of doing it. Though the nesting kind of makes me cringe, the only thing hardcoded is the top margin to get it centered vertically. Again, that can be done with an IValueConverter, but you don't want that. I'm not sure I can get any better than this, unfortunately.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication10.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Grid Background="LightBlue" Height="10" ClipToBounds="False" Margin="0,27,0,79">
<Canvas>
<Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Canvas}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=Canvas}}">
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 -40 0 0">
<Rectangle Height="40" Width="20" Fill="Black" ClipToBounds="False"/>
</Canvas>
</Grid>
</Canvas>
</Grid>
</Grid>
</Window>

Categories

Resources