Separate a Grid into multiple sections like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
</Grid>
Now create a label which centers the content in the cell.
<Label Grid.Row="0" Grid.Column="0" Content="Hello World" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
Observe that it seems to be centered.
Now, change the font of the label to anything larger than 12. The larger the better, for example 24.
<Label FontSize="24" Grid.Row="0" Grid.Column="0" Content="Hello World" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
See that the text is no longer centered.
How can I center the text into the cell keeping into account the size of the text? I don't want to specifically define a Margin for each one which does work, but it requires trial and error and is not very efficient.
I'm looking for ideally a pure WPF/XAML solution, built in or custom. Though it seems to me this functionality might require a converter and a custom style targeting a label which is unfortunate as it seems like a fair amount of effort for something so simple.
Is there an easy solution to this?
The behaviour you describe is caused by the Padding within the Label (which is not zero by default).
try:
<Label Padding="0" FontSize="30" Grid.Row="0" Grid.Column="0" Content="Hello World" HorizontalAlignment="Center" VerticalAlignment="Center">
Note: if the height for the row is too small to accomodate the fontsize, the visible part of the text will be the upper part, not the center part.
I guess it would be quiet useless for the renderer to try to center the text in that case.
I didn't understand your question clearly.But I think this is the line of code you want.I just added a col span property to the code.
< Label FontSize="24" Grid.Row="0" Background="AliceBlue" Grid.ColumnSpan="2" Content="Hello World" HorizontalAlignment="Center" VerticalAlignment="Center">< /Label>
Related
I am creating a custom calendar in XAML and WPF. The calendar is made up of seven <Grid> columns that can auto expand (e.g. width="1*") with the window.
Here's what's happening right now:
A very wide element "takes over" the columns and makes the others smaller, which is not what I want.
I want it to look like this:
In this example, the columns auto-expand to fill available width (window size) but an element can't make one column larger. The only way I know to achieve this is by setting the width property (but then it wouldn't auto-expand).
Here's sample code. It would produce output like the first image:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Hello world this is a sample very long text!" Grid.Column="1"/>
<TextBlock Text="Hello world !" Grid.Column="2"/>
</Grid>
How can I achieve this desired output?
Edit: I was using a ScrollViewer around my grid (to vertically scroll in case there were many assignments). The property HorizontalScrollBarVisibility="Hidden" actually caused this strange behavior.
I am not sure its the solution for your problem, but you can try to wrap the text if overflows, like this:
<TextBlock Text="Some long text" TextWrapping="Wrap">
Let me know if this helps, if not i can look more into it!
I'm not seeing that behavior. When I try your code snippet, the text doesn't "take over" the other columns. It gets clipped (see below)
Sample without TextWrapping
Seems like you might want to set the TextWrapping attribute of TextBlock to "Wrap".
<TextBlock Text="Hello world this is a sample very long text!" Grid.Column="1" TextWrapping="Wrap"/>
Sample with TextWrapping="Wrap"
I have a WPF application and I'm trying to get the elements positioned correctly. There are just four elements, so it should be pretty straight-forward, but I just can't get it working.
One wrinkle is that the window resizes itself to (about) the size of the desktop window when it appears, so it doesn't have a fixed size.
The elements are supposed to be stacked from top to bottom, so a Stack Panel seemed natural. But The third element has to take up all the remaining space that the top two and bottom ones don't. No matter what I tried, it either took up too much space, or too little. I could only seem to get it working if I gave it a concrete pixel size which, as explained above, won't work.
The latest thing I've tried is a Dock Panel. While it looks correct in the Visual Studio designer, when executed, the third element--a Canvas--completely covers the bottom element.
My XAML:
<DockPanel>
<Button x:Name="btnClose" DockPanel.Dock="Top" Content="X"
HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top"
Width="Auto" Height="Auto" Background="Black"
Foreground="White" Click="btnClose_Click"/>
<Label x:Name="lblTitle" DockPanel.Dock="Top" Content="My Title"
HorizontalAlignment="Center" VerticalAlignment="Top" Width="Auto"
Foreground="White" FontWeight="Bold" FontSize="22"/>
<Label x:Name="lblControls" DockPanel.Dock="Bottom" Content="Placeholder"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="Auto"
Height="Auto" Foreground="White" FontWeight="Bold" FontSize="22"/>
<Border x:Name="CanvasBorder" BorderBrush="White" BorderThickness="5" >
<Canvas x:Name="cvsChart" Grid.Row="0" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Width="Auto">
</Canvas>
</Border>
</DockPanel>
Any idea about how to get that Canvas to stretch and fill all the space the other three don't take?
UPDATE
Since #Peter Duniho pretty much proved to me that the code worked, I tried an experiment and removed the resizing code I have in place for when the window appears. Taking it out, the window appears absolutely correctly. This is what I do to resize it to (mostly) the desktop size:
public const int WINDOW_OFFSET = 10;
...
int screenWidth = (int)System.Windows.SystemParameters.PrimaryScreenWidth;
int screenHeight = (int)System.Windows.SystemParameters.PrimaryScreenHeight;
// center this window in desktop
Width = screenWidth - WINDOW_OFFSET;
Height = screenHeight - WINDOW_OFFSET;
Left = WINDOW_OFFSET/2;
Top = WINDOW_OFFSET/2;
So I did some poking around, and found a comment here on the 'Stack that said to get the WorkArea instead of the PrimaryScreenHeight. I tried that and voila!, the whole application window appears.
int screenWidth = (int)System.Windows.SystemParameters.WorkArea.Width;
int screenHeight = (int)System.Windows.SystemParameters.WorkArea.Height;
As it turns out, the bottom row was displaying, I just couldn't see it because it appeared below the bottom of the screen. Now I can see it, and I'm back to development heaven!
Thanks to everyone for their input!
There are a number of possible approaches to this. One of the most straightforward is to contain your elements in a Grid and set all but the third row height to Auto:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button x:Name="btnClose" Content="X" Grid.Row="0"
HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top"
Width="Auto" Height="Auto" Background="Black"
Foreground="White" Click="btnClose_Click"/>
<Label x:Name="lblTitle" Content="My Title" Grid.Row="1"
HorizontalAlignment="Center" VerticalAlignment="Top" Width="Auto"
Foreground="White" FontWeight="Bold" FontSize="22"/>
<Label x:Name="lblControls" Content="Placeholder" Grid.Row="3"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="Auto"
Height="Auto" Foreground="White" FontWeight="Bold" FontSize="22"/>
<Border x:Name="CanvasBorder" BorderBrush="White" BorderThickness="5" Grid.Row="2">
<Canvas x:Name="cvsChart" Grid.Row="0" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Width="Auto">
</Canvas>
</Border>
</Grid>
The default setting for a grid's row definition height is "*", which says to distribute all of the remaining space among all the rows with that setting. With only one row using that setting, it gets all of the leftover space.
This produces a window that looks like this:
(I set the window background to Gray so that your white text and border would be visible.)
Another option would in fact be to use DockPanel. It appears to me that the main problem in your attempt is that you set the lblControls element to DockPanel.Dock="Bottom" when it should be Top instead. When I change it to Top, it seems to work fine for me.
Based on your comment below, it seems you actually did want lblControls to be set to DockPanel.Dock="Bottom", and in fact the code you posted seems to also do what you want. It's not clear to me what is different from what the code you posted does and what you want it to do. It would be better if you would provide a good Minimal, Complete, and Verifiable code example that reliably reproduces the problem.
Remove the vertical alignment of the Canvas
I have a WPF application. To make the full screen visible on all screen sizes, I have implemented MinHeight, MinWidth & HorizontalAlignment="Stretch" VerticalAlignment="Stretch" in Window & Containers too. I am facing some problems when the app runs on Lower Resolution screens. The window gets cut from the right side of the screen - this doesn't show Min, Max, Close btns also on top right.
If I add layout code in then the window is proper in all resolutions, but it makes blank space above the Menubar and below end. On removing , their is no space and all is well, but right side gets cut in Low Resolution screens. And with ViewBox, space above and below the layout. My XML code is like follows :
CODE UPDATED
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- MENU BAR -->
<Menu Grid.Row="0" x:Name="myMnus" VerticalAlignment="Top" Cursor="Hand" HorizontalAlignment="Stretch" IsMainMenu="True" Grid.ColumnSpan="2">
.............
</Menu>
<ToolBarTray HorizontalAlignment="Stretch" Background="White" Margin="0,19,114,0" VerticalAlignment="Top" Grid.ColumnSpan="2" >
..............
<ToolBarTray>
<TabControl Grid.Row="1" Name="tabControl1" HorizontalAlignment="Left" Margin="0,3,0,0" VerticalAlignment="Top"
TabStripPlacement="Bottom" Grid.RowSpan="2" BorderThickness="4,25,4,1" FontSize="13">
</TabControl>
<TabControl Grid.Row="2" Name="tabControl4" HorizontalAlignment="Left" Margin="0,323,0,0" VerticalAlignment="Stretch"
TabStripPlacement="Bottom" BorderThickness="4,25,4,1" FontSize="13" Background="White" Width="227">
</TabControl>
<TabControl TabStripPlacement="Bottom" MinHeight="415" MinWidth="480" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1" Name="tabChildContainer" Margin="227,3,207,0" BorderThickness="4,25,4,1" Grid.RowSpan="2" >
</TabControl>
</Grid>
I thought by using Stretch in HorizontalAlignment and VerticalAlignment along with MinWidth and MinHeight, that it would occupy all available space horizontally and Vertically. But tabChildContainer TabControl doesn't go to the right end corner which it should go based on the code.
This is where your problem starts:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="762.976"/>
<ColumnDefinition Width="751.024"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
Anytime that you set exact pixel sizes in your UI, you're asking for exactly these kinds of problems. Setting exact sizes for sections of your application was more of a WinForms thing... WPF has numerous controls that can resize your content for you... you're using one, the Grid... just incorrectly.
Secondly, it is very unusual to use a ViewBox on your whole UI... it is not going to help you. Your best bet is to simply remove it and all of your hard-coded dimensions and make full use of the "*" and "Auto" values in your Grid. When the controls resize themselves (or a Grid resizes them) in this way, it really doesn't matter what resolution a user is using.
NOTE: This is one of the first time I'm using WPF.
I am trying to align a certain control, let's say a button for now, in the bottom right corner. But when I debug my application, it misses 8 pixels to the bottom and right. I will attach 2 pictures to show you what happens.
How do I keep the button in place?
My XAML code:
<Window x:Class="Plugin_Manager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Plugin Manager" Height="350" Width="525" Loaded="Window_Loaded_1">
<Grid x:Name="GridMain">
<Button Content="Refresh" Margin="432,288,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="75"/>
<ListView HorizontalAlignment="Left" Height="273" Margin="10,10,0,0" VerticalAlignment="Top" Width="497">
<ListView.View>
<GridView>
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
</Grid>
If you choose to use Grid layout you should try to avoid placing objects via Margin. Margin should be used to create buffer around an object, not move it to a specific point in the window. Use the layout manager's power to your advantage!
Here is a Grid example that does what you are looking for.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView Grid.Row="0" />
<Button Grid.Row="1" HorizontalAlignment="Right" Content="Push Me" />
</Grid>
I would also read up on Layout Manager in WPF. There are several; each having its own advantages & disadvantages.
Here is a DockPanel version.
<DockPanel>
<Button DockPanel.Dock="Bottom" HorizontalAlignment="Right" Content="Push Me" />
<ListView />
</DockPanel>
To create your buffer between the button and the window chrome you could do a few different things:
<Grid Margin="10"> will apply a 10 pixel space between all content and the window chrome on all side.
<Grid Margin="0,0,10,10"> would indent all content, but only on the right & bottom.
<Grid Margin="10,0,10,10"> indents all around, except the top (I commonly do this one, with a different margin value).
<Button Margin="0,0,10,10"> would indent only the button from the chrome (this is the direct answer to your comment question).
Replace the Grid above with DockPanel for the second example, or whatever other Layout Manager you are using.
A usability side note: Your confirmation buttons (I'm assuming your button will be an Ok/Cancel type button) should not be indented differently from the rest of your content. All controls that butt up against the right margin should do so at the same point (i.e., you can draw a vertical line down the right side of them all).
So, using your question's example: your button should not be indented 10 pixels to the right while your list box is not. Keeping things lined up will improve the overall look to your application.
(this ends my "usability and look-and-feel is important" side note) :)
<Button VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="5"/>
Some code example will help. Try using the alignment in xaml for your button as shown below. Ensure that the margins on the button are 0.
<Button Margin="0" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
Looking at the sample code, it is your margins and the alignment you have that are probably causing that.
Just some pointers that may help. Instead of using large margins to align the controls, I find it much easier to work with Column and Row definitions on the grid. This way you can align your controls using the grid and they will size properly as you resize your window. I attached an example in hopes it helps in your new adventures with WPF!
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="Version Date" Margin="3" VerticalAlignment="Center"/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding DateSubmitted}" Margin="3"/>
<TextBlock Grid.Column="1" Grid.Row="0" Text="Report" Margin="3" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding ReportName}" Margin="3"/>
</Grid>
I have a expander and TextBlock.
It at times overlaps for spaces.
I want the expander BringToFront.
But no such property in WPF.
How to do it?
Is seems you are using the Canvas Panel for positioning your Expander and TextBlock.
First of all: Don't use a Canvas, it's oldstyle and not flexible enough. Use one of the other Panels (i.e. Grid) to layout your Controls. Then the problem should be gone.
If you must use a Canvas and you want to prevent overlapping, you can use the Panel.ZOrder attached property. You should also set the Background property of the Expander to something opaque like "White". By default the Background property has the null-value, which means transparent.
If the issue is a design time issue:
WPF will put the last item in the XAML on top. For instance if I had this:
<TextBlock Text="one"/>
<TextBlock Text="Two"/>
TextBlock "Two" would be displayed in front of "One" because it is last in the XAML.
If it's a runtime issue bochja had it right up top with the Panel.ZOrder.
It would probably be easiest to use a Grid, so the element order doesn't matter.
Eg:
<Grid DataContext="{Binding CurrentRequest,ElementName=root}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="These labels"/>
<Label Grid.Row="0" Grid.Column="0" Content="Will overlap"/>
<Label Grid.Row="1" Grid.Column="0" Content="Next row"/>