horizontally collapsible panel in WPF - c#

I'm trying to create a side collapsible panel that include StackPanel
For that Tried use Expander like following
<Expander Width="auto" ExpandDirection="Left" HorizontalAlignment="Right">
<Expander.Header>
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel>
<Grid>
</Grid>
</StackPanel>
</Border>
</Expander.Header>
</Expander>
But this is not working properly, can't do the function that I expected.

As Maciek ƚwiszczowski said, you need to properly align your expander and put the contents inside the context section of the expander. Also, assuming you want it to fill the entire left section, I would recommend you use a Grid to hold it all, like so:
Example:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Expander ExpandDirection="Right" HorizontalAlignment="Left">
<Border BorderBrush="Black" BorderThickness="1">
</Border>
</Expander>
</Grid>
Here's what it looks like (I put a blue background and some text in the expander, and just a red stack panel in the second column in order to make it really clear).
Expanded:
Collapsed:

Related

Make texts look the same size in xaml

I write an XAML application and I have a problem with the size of text. How can I make the texts look complete but with the same size? (make it responsive).
This is a small example of my XAML code:
<!-- (0, 0) Availability -->
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Viewbox Stretch="Uniform">
<Grid Grid.Column="0">
<TextBlock Style="{StaticResource OeeText}">Disponibilidad</TextBlock>
</Grid>
</Viewbox>
<Grid Grid.Column="1">
<TextBlock Style="{StaticResource OeeValues}">100%</TextBlock>
</Grid>
</Grid>
In the Window App, the text shows as:
How can I make all three texts look the same size?
Thanks )
You may define the size of a textBox in a responsive manner using the ViewBox Component but you have to use it inside the grid , in order to wrap the textBox Control
<Viewbox Stretch="Uniform" MaxWidth="200" MaxHeight="200" MinWidth="100" MinHeight="100">
<TextBox x:Name="MyTextBox" />
</Viewbox>
You may also control the size by setting its max/min of width and height as mentioned in the docs

WPF How do I make a Border width expand to fill available space in a DockPanel

I have a custom control ButtonRow which will end up going into a different control.
It is very simple, it has one Border, on label and one button.
I need to make it so that the border will extend its width to fill up to where the button is.
This is not happening as you can see in the below image:
The XAML can be found below. I have tried fiddling about with the horizontal alignment of both he label and the border, but they will only ever re-size to fit the text content of the label.
I know there are existing question with very similar problems and names, but none have needed to do quite the same thing or have helped me solve my problem.
I have tried using a StackPanel in horizontal alignment but all it did was make the button go next to the border.
How can I make the border expand to fill the available space?
<Grid>
<DockPanel Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="dockPanel1" VerticalAlignment="Top" Width="Auto">
<Border BorderBrush="#FFDADFE1" Background="#FFECF0F1" BorderThickness="1" Height="20" Name="bdrFilter" HorizontalAlignment="Stretch">
<Label Content="Filter..." FontStyle="Italic" Foreground="#FF6C7A89" Height="20" Name="lblFilter" Padding="5,0" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" />
</Border>
<Button Style="{StaticResource FlatButtonStyle}" Content="+" Height="20" HorizontalAlignment="Right" Name="btnAddFilter" VerticalAlignment="Top" Width="20" Foreground="#FF6C7A89" ForceCursor="True" BorderBrush="{x:Null}" />
</DockPanel>
</Grid>
(The button style does not affect its alignment or any other relevant properties)
A DockPanel is not the correct Panel to use for this requirement... like a StackPanel, it does not resize its contents. Instead, just use a regular Grid (which also uses less resources than a DockPanel):
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border BorderBrush="#FFDADFE1" Background="#FFECF0F1" BorderThickness="1"
Height="20" Name="bdrFilter" VerticalAlignment="Top">
<Label Content="Filter..." FontStyle="Italic" Foreground="#FF6C7A89"
Height="20" Name="lblFilter" Padding="5,0" />
</Border>
<Button Grid.Column="1" Content="+" Height="20" HorizontalAlignment="Right"
Name="btnAddFilter" VerticalAlignment="Top" Width="20" Foreground="#FF6C7A89"
ForceCursor="True" BorderBrush="{x:Null}" />
</Grid>
Please see the Panels Overview page on MSDN for more information about the different Panels in WPF.
This might help you out. Setting LastChildFill=True inside a DockPanel does exactly what the name suggests.

Creating a button Template

I'm trying to create a template for a button that I can use over and over again on a form.
The Button, I want it to contain a Grid with two rows and a custom piece of text within the bottom row.
This is what I've got so far, but I don't think it's right because I want to set the text from within the button element.
<ControlTemplate TargetType="Control">
<Grid Width="444">
<Grid.RowDefinitions>
<RowDefinition Height="51" />
<RowDefinition Height="36" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#286c97"></Grid>
<Grid Grid.Row="1" Background="#5898c0">
<TextBlock Grid.Row="1" FontFamily="Segoe UI" FontSize="12" Text="{TemplateBinding Content}" />
</Grid>
</Grid>
</ControlTemplate>
Then to call the template I was hoping I could go:
<Button Content="This is the text" />
But sadly this doesn't work. Is there some other template that I'm supposed to be using to pass the text value to it?
To make it work, there is a control called ContentPresenter. Place that inside your template wherever you want it to be. But remember, that it could be anything, a text, an image or a bunch of other controls, and your Button nor your ControlTemplate, should not care about what it is.
ControlTemplate TargetType="Control">
<Grid Width="444">
<Grid.RowDefinitions>
<RowDefinition Height="51" />
<RowDefinition Height="36" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#286c97"></Grid>
<Grid Grid.Row="1" Background="#5898c0">
<ContentPresenter/>
</Grid>
</Grid>
</ControlTemplate>
The ContentPresenter, when used inside a ContentControl, like the button, automatically attaches to the Content, ContentTemplate and ContentTemplateSelector properties of the templated parent.
Now if you want to display more than just Text, or want to customize the text more, just pass a DataTemplate as your ContentTemplate directly to the specific button.
<DataTemplate x:Key="myButtonContentTemplate">
<TextBlock FontSize="18" Text="{Binding}"/>
</DataTemplate>
<Button ContentTemplate="{StaticResource myButtonContentTemplate}"/>

inter related stack panel sizing

I have a recursively defined user control that needs the following properties:
there are two columns
the first contains a single border around some text
the second column contains a stack of these same type of controls (the recursive part)
if the box in the first column is shorter than the total height of the stacked boxes in the second column, the box should expand to make both columns the same height.
If the total height of the second column is shorter than the box in the first column, then the last item in the second column's stack should expand so they are the same height.
so for example, it might look like this:
Ok, so far what I have done is create a horizontal stack panel where the first item is a dock-panel containing a border and text... the second column is a vertical stack panel bound to a sublist, creating the recursive user control... like this..
<StackPanel Orientation="Horizontal" Background="AliceBlue">
<local:TMRequirementView Requirement="{Binding Baseline}" />
<StackPanel Orientation="Vertical">
<ItemsControl ItemsSource="{Binding Requirements}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:TMGridView Baseline="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Where the requirement looks like this:
<DockPanel>
<Border MinHeight="50"
BorderBrush="Black" BorderThickness="2">
<TextBlock Text="{Binding Description}"
TextWrapping="Wrap" Background="Transparent" Height="Auto" />
</Border>
</DockPanel>
Now this works great if the stacked column is taller, but it doesn't work if the first column is taller, and I get gaps. Any idea how to handle this mutual height dependency?
Update:
So by adding a border around the right columns stack panel, I was able to see that the stackpanel actually did receive the min-height changes. However, even though there was room to expand, the children of the stack panel didn't automatically update. If I fix the minheight of the stack panel before hand to something large, the children fill up. What I need to figure out is how to update the chidren's height based on changes to the stack panel's min-height.
I think the Grid in this layout does what you describe. I put it in a DockPanel so that you can see how it resizes. Try typing stuff into the text boxes and watch how it behaves:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
<Grid DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox AcceptsReturn="True" Grid.Row="0" Grid.Column="0" Grid.RowSpan="3"></TextBox>
<TextBox AcceptsReturn="True" Grid.Row="0" Grid.Column="1"></TextBox>
<TextBox AcceptsReturn="True" Grid.Row="1" Grid.Column="1"></TextBox>
<TextBox AcceptsReturn="True" Grid.Row="2" Grid.Column="1"></TextBox>
</Grid>
<TextBlock/>
</DockPanel>
</Page>
All three rows of the Grid will have the height of a TextBox at a minimum (when you replace the TextBoxes with other elements, you'll need to set minimum heights to keep them from vanishing if they're empty). Since the third row is star-sized, it will size itself to all remaining vertical space left after the first two rows are arranged. So if there's a bunch of content in the first column, the third row in the second column gets taller.
Edit
Actually, there's no reason to even screw around with a Grid in this case: What you're describing is really the behavior of the DockPanel:
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<DockPanel.Resources>
<Style TargetType="Label">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="Background" Value="Lavender"/>
<Setter Property="Margin" Value="1"/>
</Style>
</DockPanel.Resources>
<DockPanel LastChildFill="True">
<Label>Foo</Label>
</DockPanel>
<DockPanel LastChildFill="True">
<Label>Foo</Label>
<Label>Bar</Label>
<Label>Baz</Label>
<Label>Bat</Label>
</DockPanel>
</DockPanel>
<Label/>
</DockPanel>

How to have a control fill all available space

I have a xaml code:
<Grid>
<WrapPanel>
<TextBox ></TextBox>
<Button Content="GetIt" />
</WrapPanel>
</Grid>
How i can to get all available space for textBox?
i want to do something like that:
|[____________________][GetIt]|
There are a number of ways this can be achieved, including this one:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox />
<Button Grid.Column="1">GetIt</Button>
</Grid>
Try this:
<Grid>
<TextBox HorizontalAlignment="Stretch" Margin="2,2,102,2"></TextBox>
<Button HorizontalAlignment="Right" Width="100" Content="GetIt" />
</Grid>
Just make the button the desired width and the text box will fill up the rest.
Thanks for the catch; corrected above to properly handle margin on right. This does, however, require you to update the margin when the button width changes. Two columns is a better solution if you plan to change the spacing often. Using the margin is cleaner if you have several controls in the grid and don't want to create nested grids to handle this kind of split.
The simplest way is to use a DockPanel instead of a Grid (the default for LastChildFill is true but I also added it here for clarity):
<DockPanel LastChildFill="True">
<Button Content="GetIt" DockPanel.Dock="Right" />
<TextBox ></TextBox>
</DockPanel>
Here's a way to achieve the layout that you're looking for:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style TargetType="TextBox">
<Setter Property="Margin" Value="2"/>
</Style>
</Page.Resources>
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<!-- Because the Button is fixed in size, you can divide the row it's
in using a DockPanel: the Button is docked to the right edge, and the
TextBox fills up the remaining available space. -->
<Button Margin="2" Padding="2" DockPanel.Dock="Right">GetIt</Button>
<TextBox />
</DockPanel>
<!-- Because the TextBoxes *aren't* fixed in size, you can't use docking,
as it won't size them. So put them in a Grid and use star sizing to
divide the grid's vertical space into two equal parts. The Grid will
fill up the remainder of the (outer) DockPanel. -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0">Another TextBox</TextBox>
<TextBox Grid.Row="1">Yet another TextBox</TextBox>
</Grid>
</DockPanel>
</Page>

Categories

Resources