I have a button with a StackPanel, I want to align StackPanel to center according to first TextBox (maintext).
<Button Style="{StaticResource NumPadStyle}" Grid.Column="0" Grid.Row="2" Tag="7" >
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource NumPadMainText}" Name="maintext">7</TextBlock>
<TextBlock Style="{StaticResource NumPadSubText}" Name="subtext">PQRS</TextBlock>
</StackPanel>
</Button>
current:
desired:
Taking into consideration that it seems that all the buttons have the same size, you could use a grid with Columns of even size, to be sure that your texts will be positions in the same way in all the buttons.
<Button Style="{StaticResource NumPadStyle}" Grid.Column="0" Grid.Row="2" Tag="7">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
Style="{StaticResource NumPadMainText}" Name="maintext">7</TextBlock>
<TextBlock Grid.Column="2" HorizontalAlignment="Left"
Style="{StaticResource NumPadSubText}"
Name="subtext">PQRS</TextBlock>
</Grid>
</Button>
LE: You can replace the Width="Auto" value in the Column to a fixed value, like Width="20" or something, in case you want all NumPadSubTexts to start from the same location in all buttons.
Set MinWidth (adjust it coherently with the fontsize) to StackPanel:
<StackPanel Orientation="Horizontal" MinWidth="35">
<TextBlock Style="{StaticResource NumPadMainText}" Name="maintext">7</TextBlock>
<TextBlock Style="{StaticResource NumPadSubText}" Name="subtext">PQRS</TextBlock>
</StackPanel>
Related
I have a very basic layout, but still not able to get the behaviour I want. Stupid me...
My grid has two columns, dynamic sized column left and fixed sized column right. This is working. Inside the right column I have stackpanel containing two buttons, they follow the window resizing correctly.
Inside the left column I have dockpanel containing two groupboxes, the lower has fixed height and is docked to the bottom. This groupbox follows the window resizing correctly, just like I want.
But I'm not able to get the upper groupbox to fill the upper section of the dockpanel. I can only set its height as fixed or when setting it "Auto" it gets strange height of 23...? I want it to fill the area and follow window resizing. I tried using stackpanel also in this column, but no success.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="220"/>
</Grid.ColumnDefinitions>
<DockPanel x:Name="GroupPanel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<GroupBox x:Name="AlarmGroup" Header="Alarms" Margin="10" DockPanel.Dock="Top" />
<GroupBox x:Name="LogGroup" Header="Log" Height="188" Margin="10" VerticalAlignment="Bottom" />
</DockPanel>
<StackPanel x:Name="ButtonPanel" Width="190" Grid.Column="1">
<Button x:Name="StartButton" DockPanel.Dock="Right" Width="150" Height="40" VerticalAlignment="Top" Margin="0,20,10,0">Start</Button>
<Button x:Name="StopButton" DockPanel.Dock="Right" Width="150" Height="40" VerticalAlignment="Top" Margin="0,10,10,0">Stop</Button>
</StackPanel>
</Grid>
By default, DockPanel fills its remaining space with its last child.
You've set the AlarmGroup GroupBox as the first child, so it takes up only the space it needs; it's default. The second child has a fixed height, so it does not take up the remainder of the space.
To achieve the layout you are looking for, move LogGroup to be the first child of GroupPanel and set its DockPanel.Dock property to Bottom.
Example
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="220"/>
</Grid.ColumnDefinitions>
<DockPanel x:Name="GroupPanel">
<GroupBox x:Name="LogGroup" Header="Log"
DockPanel.Dock="Bottom"
Height="188" Margin="10"/>
<GroupBox x:Name="AlarmGroup" Header="Alarms"
DockPanel.Dock="Top"
Margin="10"/>
</DockPanel>
<StackPanel x:Name="ButtonPanel"
Width="190"
Grid.Column="1">
<Button x:Name="StartButton"
Width="150" Height="40"
VerticalAlignment="Top"
Margin="0,20,10,0">Start</Button>
<Button x:Name="StopButton"
Width="150" Height="40"
VerticalAlignment="Top"
Margin="0,10,10,0">Stop</Button>
</StackPanel>
</Grid>
Result
Is this working for you ?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="220"/>
</Grid.ColumnDefinitions>
<DockPanel x:Name="GroupPanel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<GroupBox x:Name="LogGroup" Header="Log" Height="188" Margin="10" DockPanel.Dock="Bottom"/>
<GroupBox x:Name="AlarmGroup" Header="Alarms" Margin="10" DockPanel.Dock="Top" />
</DockPanel>
<StackPanel x:Name="ButtonPanel" Width="190" Grid.Column="1">
<Button x:Name="StartButton" DockPanel.Dock="Right" Width="150" Height="40" VerticalAlignment="Top" Margin="0,20,10,0">Start</Button>
<Button x:Name="StopButton" DockPanel.Dock="Right" Width="150" Height="40" VerticalAlignment="Top" Margin="0,10,10,0">Stop</Button>
</StackPanel>
</Grid>
In a DockPanel there is a property LastChildFill set to true by default which means that the last coltrol you put will take all the space. I also changed VerticalAligment="Bottom" to DockPanel.Dock="Bottom"
Depending on the screen size, Log and Alarm screens get smaller equally. I tried to do it by dividing it into partitions in a Grid. Is it enough for you ?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="220"/>
</Grid.ColumnDefinitions>
<Grid x:Name="GroupPanel" Grid.Column="0" Grid.Row="0" Grid.RowSpan="3">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="10"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<GroupBox x:Name="LogGroup" Header="Log" Grid.Column="0" Grid.Row="0" Margin="10"/>
<GroupBox x:Name="AlarmGroup" Header="Alarms" Grid.Column="0" Grid.Row="2" Margin="10"/>
</Grid>
<StackPanel x:Name="ButtonPanel"
Width="190"
Grid.Column="1">
<Button x:Name="StartButton"
Width="150" Height="40"
VerticalAlignment="Top"
Margin="0,20,10,0">Start</Button>
<Button x:Name="StopButton"
Width="150" Height="40"
VerticalAlignment="Top"
Margin="0,10,10,0">Stop</Button>
</StackPanel>
</Grid>
I created my own simple statusbarcontrol with 3 TextBlocks. Now I would like that the first Textblock takes as much space as it has available. That I don't seem to get done.. Now it only takes the space needed to display the text.
XAML:
<StatusBar Background="{StaticResource GradientBrush}">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem HorizontalAlignment="Left"
HorizontalContentAlignment="Right">
<Border BorderThickness="1"
BorderBrush="Black"
Padding="5 0 5 0"
Background="White">
<TextBlock Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding TextColorMessage}"
Background="White"
/>
</Border>
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=DatabaseName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StatusBarItem>
<Separator Grid.Column="3" />
<StatusBarItem Grid.Column="4"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=ComputerName}" />
</StatusBarItem>
Well this is pretty straight forward:
you had set the StatusBarItem HorizontalAlignment="Left" when it should be "strech", same for the HorizontalContentAlignment.
Also would suggest setting margin=0 on the border.
this is what i did so it will work for me:
<StatusBarItem HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Border BorderThickness="1"
BorderBrush="Black"
Margin="0"
Padding="5 0 5 0"
Background="White">
<TextBlock Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding TextColorMessage}"
Background="White"/>
</Border>
</StatusBarItem>
if this is helpful please mark as answer
Try setting the StatusBarItem's HorizontalAlignment and HorizontalContentAlignment to Stretch.
Set the StatusBarItem's HorizontalContentAlignment to Stretch and the TextBlock's TextAlignment property to Right. (This second setting is only needed for the first StatusBarItem as it seems that you try to align the text to the right in it.)
StatusBar has only one HorizontalAlignment=Right item to effect, so you can get only the last item in wanted place. You can set statusBar's FlowDirection="RightToLeft" and add item in reversed order. Details: right placed items needn't StatusBarItem surrounded, but the left one need to be streched. Following code:
<StatusBar VerticalAlignment="Bottom" FlowDirection="RightToLeft"><!--flow right to left cause items right aligned-->
<!--make item's flow back left to right, avoid display disorder-->
<TextBlock x:Name="textBlock_status_R1" Text="111.147.168.20" Grid.Column="2" Margin="10,0" FlowDirection="LeftToRight"/>
<Separator/>
<TextBlock x:Name="textBlock_status_R2" Text="Working" Margin="10,0" FlowDirection="LeftToRight"/>
<Separator/>
<!--To fill rest space,need StatusBarItem packing and default HorizontalAlignment="Stretch"-->
<StatusBarItem FlowDirection="LeftToRight">
<TextBlock x:Name="textBlock_status_L1" Text="Information here."/>
</StatusBarItem>
</StatusBar>
I'm having a problem achieving the layout i want.
This is my code:
<DockPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" LastChildFill="True">
<Label DockPanel.Dock="Left" Content="Add new:"/>
<Button DockPanel.Dock="Right" Content="Add" VerticalAlignment="Center"/>
<ComboBox VerticalAlignment="Center" MaxWidth="150" HorizontalAlignment="Stretch">
<System:String>Item1</System:String>
<System:String>Item2</System:String>
<System:String>Item3</System:String>
</ComboBox>
</DockPanel>
What I want is to have the three elements aligned to the right, in the order Label, ComboBox, Button. The Label and the button should take as much space as needed, but I want the ComboBox to take as much space as possible up to 150 px.
It kind of works when the DockPanel is not set to HorizontalAlignment=Right.
Any tips/solutions?
Thanks.
Use the RightToLeft setting, like this:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid FlowDirection="RightToLeft">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label FlowDirection="LeftToRight" Grid.Column="2" Content="Add new:"/>
<ComboBox FlowDirection="LeftToRight" Grid.Column="1" VerticalAlignment="Center" MaxWidth="150" HorizontalAlignment="Stretch">
<ComboBoxItem>Test</ComboBoxItem>
<ComboBoxItem>Test</ComboBoxItem>
<ComboBoxItem>Test</ComboBoxItem>
</ComboBox>
<Button FlowDirection="LeftToRight" Grid.Column="0" DockPanel.Dock="Right" Content="Add" VerticalAlignment="Center"/>
</Grid>
</Grid>
Here is is running:
I am trying to get a layout where an icon floats on the right end of a textblock; the textblock grows/shrinks to content. I cannot make this happen without the textblock running outside the grid. For example:
<Grid x:Name="LayoutRoot" Width="500" HorizontalAlignment="Left" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="0" >
<TextBlock.Text>longer keeps going and going testgrand you going and then t
</TextBlock.Text>
</TextBlock>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="1"/>
</Grid>
Seems like the natural approach and works fine when the text is shorter than the column/grid, except the textbox and column will grow indefinitely and not honor the bounds of the grid.
The inverse, with the icon on the left, works fine with a simpler layout, and the textblock doesn’t grow indefinitely. This is achieved with this markup:
<Grid Grid.Row="1" Width="500" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="0"/>
<TextBlock x:Name="textBlock2" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock.Text>longer testgrow the textblock and it will just keep growing but it will stop when it gets too </TextBlock.Text>
</TextBlock>
</Grid>
Any help appreciated. If a grid won’t work, is there an alternate layout where I can get the icon floating on the right of the text, and the textblock will trim text when it’s too long?
Also:
No, using * size columns doesn't work because the columns are fixed, and the icon won't float at the end of the text
A DockPanel doesn't work either, or at least I or others I've asked haven't been able to. The best it can do is to have the icon half-cut-off outside the dockpanel's right side.
Can you get what you want by setting MaxWidth on the TextBlock? If you add MaxWidth="460" to your first example:
<Grid x:Name="LayoutRoot" Width="500" HorizontalAlignment="Left" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock MaxWidth="460" x:Name="textBlock" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="0" >
<TextBlock.Text>longer keeps going and going testgrand you going and then t</TextBlock.Text>
</TextBlock>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="1"/>
</Grid>
Then the TextBlock will grow horizontally and always have the rectangle immediately on its right. It won't be wider than 460, so the TextBlock plus the Rectangle shouldn't be wider than 500. If you need the Grid to resize dynamically then you can bind TextBlock.MaxWidth to Grid.ActualWidth with a converter that subtracts the width of the Rectangle.
Edit:
Actually, it should be even simpler than that. Use star sizing on the columns, but set MaxWidth instead of Width on the Grid. That way, the grid itself will get smaller when the text is smaller so that the rectangle is always at the edge of the text.
<Grid x:Name="LayoutRoot" MaxWidth="500" HorizontalAlignment="Left" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="0" >
<TextBlock.Text>longer keeps going and going testgrand you going and then t</TextBlock.Text>
</TextBlock>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="1"/>
</Grid>
Someone internally suggested this answer, which works:
<WrapPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<AccessText TextTrimming="CharacterEllipsis" Grid.Column="0" Margin="0,0,4,0" Text="type more typingon the long hi longer than what if you keep tyingin and get to the end and that's why it changed because you were in the middle" />
<Border Grid.Column="1" Width="10" Height="10" Background="Red" />
</Grid>
</WrapPanel>
The wrappanel seems to provide the necessary magic. I haven't tried Quartermeister's but will save it for future reference!
Our final layout is more complicated and looks like this (it's the header bar for an expander):
<WrapPanel Orientation="Vertical">
<Grid x:Name="HeaderSite" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" /> <!-- 7/14: fix from list: wrap the whole thing in a wrappanel. Allows for one * col. -->
<ColumnDefinition Width="19" />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="buttonExpanderToggleButton"
Height="20" VerticalAlignment="Top"
/>
<Image x:Name="imageActivityIcon" Grid.Column="1"
Height="16" Width="16"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="0"/>
<AccessText x:Name="textActivityID"
Grid.Column="2"
VerticalAlignment="Top" Margin="5,2,0,0"
TextTrimming="CharacterEllipsis"
FontSize="12" HorizontalAlignment="Left" Text="MA77777"/>
<AccessText x:Name="textActivityHeader"
Grid.Column="3"
VerticalAlignment="Top" Margin="0,2,0,0"
TextTrimming="CharacterEllipsis"
FontSize="12" HorizontalAlignment="Left" Text="Title title title title aand Title title title title a little and if you type more what happens as you keep typing "/>
<AccessText x:Name="textActivityStatus"
FontWeight="Normal"
FontStyle="Italic"
Grid.Column="4"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Top" Margin="0,2,8,0"
FontSize="12" HorizontalAlignment="Left" Text="(On Hold)"/>
<Image x:Name="imageLink"
Stretch="None" VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="5"/>
</Grid>
</WrapPanel>
This works fine too even with the other auto sized columns. The key seems to be the wrappanel and the one * sized column. If you set them all to auto it doesn't work.
I hope this and Quartermeister's answer helps somebody, because this drove me #$%#$% crazy.
The below code will result in the following output, is that what you are looking for???
longer keeps going and going... [red rectangle]
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="longer keeps going and going testgrand you going and then t" TextTrimming="CharacterEllipsis"/>
<Rectangle Grid.Column="1" Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" />
</Grid>
I had a somewhat similar problem; I wanted to show some content with an externally-sized border area but containing two TextBlocks, where the first is auto-sized and the second is fixed-sized, and the second floats left as the first gets smaller but stops at the right edge (so the first block's text is clipped instead of the second becoming invisible).
Distilling the previous answers, it appears that the key bit of magic is simply to use HorizontalAlignment="Left" with the first column set to star-sized.
<Border BorderThickness="1" BorderBrush="Black">
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Value}" />
<TextBlock Grid.Column="1" Text="⏫" Margin="4,0,0,0" Foreground="Blue" />
</Grid>
</Border>
It appears that the way this works is that (a bit counter-intuitively) the Border stays full width (as set by its parent layout), while the Grid will size to its content -- except that it will not get wider than the containing Border. This keeps the second TextBlock visible.
Probably I'm just missing something obvious, but I can't get the image in my DataTemplate to align to the right in the Grid, so that when the window is stretched, the image is "pulled" to the right as well:
<Window.Resources>
<DataTemplate x:Key="PersonTemplate" DataType="Minimal.Client.Person">
<Border BorderBrush="Purple" BorderThickness="2" CornerRadius="2" Padding="5" Margin="5">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="200"/>
<ColumnDefinition Width="Auto" MaxWidth="200"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column ="0" Orientation="Horizontal" >
<TextBlock FontFamily="Verdana" FontSize="16" FontWeight="Bold" Text="{Binding LastName}" />
<TextBlock FontFamily="Verdana" FontSize="16" Text=", " />
<TextBlock FontFamily="Verdana" FontSize="16" Text="{Binding FirstName}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Vertical" HorizontalAlignment="Right">
<Border BorderBrush="Black" BorderThickness="1">
<Image Source="{Binding Picture}" Width="180" Height="150" />
</Border>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
Any suggestions?
I think the problem is that you have set a MaxWidth of 200 for the second column (where the Image is contained). Therefore, the column will not be any wider than 200 pixels and the two columns will not use the complete available space. If you insert another column in between the two columns and make this one star-sized, the Image will be right-aligned:
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" MaxWidth="200"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column ="0" Orientation="Horizontal" >
<TextBlock FontFamily="Verdana" FontSize="16" FontWeight="Bold" Text="{Binding LastName}" />
<TextBlock FontFamily="Verdana" FontSize="16" Text=", " />
<TextBlock FontFamily="Verdana" FontSize="16" Text="{Binding FirstName}" />
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Vertical" HorizontalAlignment="Right">
<Border BorderBrush="Black" BorderThickness="1">
<Image Source="{Binding Picture}" Width="180" Height="150" />
</Border>
</StackPanel>
</Grid>
This way, it works for me. However, you should be careful when using StackPanels. They always take as much space as they need. And if they are not given that much space, part of the content will simply be hidden.
gehho.
Try taking out the "MaxWidth" from your second column definition, and setting the Width to "*".
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
This keeeps the explicit settings from positioning your second column to the left.