How to automatically size TabControl in a DockPanel - WPF - c#

I have a simple WPF Forms app. I have a DockPanel as my root panel. The first child is a StackPanel that has some controls in it, then the second control is a TabControl. What I want, and the panel types can change all they want is for the TabControl to maintain the fill size of the window except for what the first StackPanel consumes. However no matter what I try the TabControl seems to change its size depending on whats inside it, not whats it is inside of.
<Window>
<DockPanel>
<StackPanel> </StackPanel>
<TabControl> </TabControl>
</DockPanel>
</Window>

Just set the HorizontalAlignment and VerticalAlignment properties of your TabControl to "Stretch":
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="5">
<TextBlock Text="Hello" />
<TextBlock Text="World" />
</StackPanel>
<TabControl HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TabItem Header="Small">
<TextBlock Text="Just Some Small Stuff" />
</TabItem>
<TabItem Header="Bigger">
<StackPanel>
<TextBlock Text="One line" />
<TextBlock Text="The next line" />
</StackPanel>
</TabItem>
</TabControl>
</DockPanel>

Related

Setting VerticalContentAlignment in my WPF TabItem changes both the text in the tab and the Control contained in the tab

<TabItem Header="Data Entry"
FontSize="40"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Center"
VerticalAlignment="Center"
Height="75"
Width="300"
Background="#464646"
Foreground="White"
DataContext="{Binding Tabs[0]}">
<Controls:DataEntryUserControl />
</TabItem>
My TabItem is formed with the code above. I want the text in the tab ("Data Entry") to be aligned to the center of the tab, but I want the UserControl to be aligned to the top of the window. However, both of these alignments change when I set VerticalContentAlignment (e.g. in the code above, both of them are aligned to the top of their respective parents). The VerticalAlignment property doesn't change anything.
How can I accomplish this?
Define a HeaderTemplate where you specify the alignment of the header:
<TabItem Header="Data Entry"
FontSize="40"
Height="75"
Width="300"
Background="#464646"
Foreground="White"
DataContext="{Binding Tabs[0]}">
<TabItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" HorizontalAlignment="Center" />
</DataTemplate>
</TabItem.HeaderTemplate>
<Controls:DataEntryUserControl />
</TabItem>

WPF Expander overlay used in ItemsControl

I've been searching for some time but all solution I find only tackle parts of my issue.
I'd like to have an ItemsControl with each item containing an Expander. On expanding, the Expander's content should be shown as an overlay overlapping the other items in the ItemsControl and not moving them down.
The following XAML-Code does exactly as supposed to with one big issue: The Expander's content does not overlap the other items but is hidden behind them. I suppose this is due to the ZIndex as the following items in the ItemsControl are added after the Expander's content.
I managed to set one single Expander's ZIndex to 99 using style triggers but this seems to be a too complicated and error-prone solution. Any thoughts?
<Window x:Class="WpfTest.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">
<Window.Resources>
<x:Array x:Key="items"
Type="sys:String"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String>One</sys:String>
<sys:String>Two</sys:String>
<sys:String>Three</sys:String>
<sys:String>Four</sys:String>
</x:Array>
<DataTemplate x:Key="template">
<Grid Background="Red" Margin="0,0,0,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding}" />
<Canvas Height="25" Grid.Row="1">
<Expander ExpandDirection="Down" Header="Header" Grid.Row="1">
<Expander.Content>
<TextBlock Height="80" Text="Content" Background="Yellow" />
</Expander.Content>
</Expander>
</Canvas>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ScrollViewer>
<ItemsControl ItemsSource="{StaticResource items}"
ItemTemplate="{StaticResource template}"
HorizontalContentAlignment="Stretch">
</ItemsControl>
</ScrollViewer>
</Grid>
</Window>
It's going to be tricky to achieve this in the way you are attempting it. The problem is the nested structure -- since each Canvas is nested inside a Grid, you won't be able to control its z-index relative to other Canvas element. To illustrate this, here is a schematic of the visual tree created by your current markup:
<StackPanel> <!-- items panel -->
<ContentPresenter> <!-- item wrapper -->
<Grid>
<Canvas>
</Canvas>
</Grid>
</ContentPresenter>
<ContentPresenter> <!-- item wrapper -->
<Grid>
<Canvas>
</Canvas>
</Grid>
</ContentPresenter>
</StackPanel>
With reference to the above, your goal will be to have the Canvas elements appear in front of the siblings of its parent ContentPresenter. This is impossible in this hierarchy, because ZIndex only applies relative to siblings of the same parent element. Now, there might be ways you could massage the above into a flat structure so that you could then apply ZIndex your expanded content as needed.
However, I think an easier and more natural approach would be to use Popup elements for the expanded content. A Popup is a framework primitive that is located outside of the visual tree, and will always sit on top of your other content. You can use a ToggleButton or something similar to create the "expand" effect. For example:
<StackPanel Grid.Row="1">
<ToggleButton x:Name="PopupToggle" Content="Expand" />
<Popup IsOpen="{Binding IsChecked,ElementName=PopupToggle}">
<TextBlock Height="80" Text="Content" Background="Yellow" />
</Popup>
</StackPanel>

A ListBox inside a stackpanel doesn't work

I have these controls:
<StackPanel>
<TextBlock Text="Bill Benson"/>
<Image Source="/Assets/Images/BB.png"/>
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text=""/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Text="ends: 2015"/>
</StackPanel>
ListBox may have any number of items inside it. I want the whole page scroll from top to bottom, but it doesn't scroll down-up. How can I do that? I know the problem is because a scrollable control inside another scrollable one, but don't know how to fix it.
You need to assign the height to the listbox control, as it is taking an auto which means that the height keeps on increasing according to the count of items in it, so its impossible to access the items in the bottom of the control, So either give it a height or instead of stackpanel keep it in a grid with row definitions.
<StackPanel>
<TextBlock Text="Bill Benson"/>
<Image Source="/Assets/Images/BB.png"/>
<ListBox Height="200">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text=""/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Text="ends: 2015"/>
</StackPanel>
Try specifying a height for your controls, especially StackPanel and ListBox, even just an "Auto" Height could work for testing. Also, rather than setting an ItemTemplate, which would be more useful if you had a List of items to bind the ListBox to, try some hardcoded values:
<ListBox>
<TextBlock Text="1"/>
<TextBlock Text="Test"/>
<TextBlock Text="Another"/>
<TextBlock Text="testing"/>
<TextBlock Text="Sample"/>
</ListBox>
Try to add more than the ListBox can show, and see if it scrolls.
Try a dock panel instead:
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<TextBlock Text="Bill Benson"/>
<Image Source="/Assets/Images/BB.png"/>
</StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="ends: 2015"/>
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text=""/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
The ListBox will automatically expand to fill the space. Note: It has to be the last child in the DockPanel. (You can change this functionality using LastChildFill="False")

C# WPF Set Focus TabItem

I have a TabControl and i want to set the focus on the firsttab on a Textbox.
I tried to use in Code:
this.tabItemMerkmalAllgemein.Focus();
this.textBoxMerkmalBezeichnung.Focus();
If the second tab was selected the first Tab will be selected after this but no Cursor at the Textbox is shown, so the Textbox focus dosen't work.
XAML TabControle:
<TabControl Width="359" Grid.Column="1" Style="{StaticResource EditDialogTabControl}" Name="tabControlMerkmalDetails" Margin="4,0,0,0">
<TabItem Header="Allgemein" Name="tabItemMerkmalAllgemein" GotFocus="tabItemMerkmalAllgemein_GotFocus">
…
<Label Grid.Row="0" Style="{StaticResource EditDialogLabel}" Content="Bezeichnung"/>
<TextBox x:Name="textBoxMerkmalBezeichnung" Grid.Row="0" Grid.Column="1"
Style="{StaticResource EditDialogTextBox}" MaxWidth="300"
Text="{Binding Path=bezeichnung, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextChanged="textBoxMerkmalBezeichnung_TextChanged" LostFocus="textBoxMerkmalBezeichnung_LostFocus" />
…
</TabItem>
<TabItem Name="tabItemKostenpflichtig">
…
</TabItem>
</TabControl>
</Grid>
</TabItem>
You need to change your declaration of the TabItem to this:
<TabItem FocusManager.FocusedElement="{Binding ElementName=textBoxMerkmalBezeichnung}"
Header="Allgemein" Name="tabItemMerkmalAllgemein" GotFocus="tabItemMerkmalAllgemein_GotFocus">
The important part is the addition of the FocusManager.FocusedElement attached property. You can find out more from the FocusManager.FocusedElement Attached Property page at MSDN.

Listbox extending off the page

I have a listbox inside of a stack panel inside of a border in a silverlight application and when ever I add anything to the listbox it increases in height so the scrollbar is never used and it extends beyond the boundaries of the border element. I have tried explicitly setting the height attribute of the listbox, the border and the stack panel and it still goes beyond this.
Here is my code:
<Border x:Name="articlePane">
<StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
<Button Content="Latest" MouseEnter="HandleRollInAnimation" MouseLeave="HandleRollOutAnimation" />
<Button Content="Pending" MouseEnter="HandleRollInAnimation" MouseLeave="HandleRollOutAnimation" />
<Button Content="Done" MouseEnter="HandleRollInAnimation" MouseLeave="HandleRollOutAnimation" />
</StackPanel>
<ListBox x:Name="articleList" Margin="5" Background="Transparent" ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Center">
<Image x:Name="articleImage" />
<TextBlock x:Name="articleTitle" Text="{Binding Path=Title}" FontSize="18" FontWeight="Bold"
Margin="5"/>
<TextBlock x:Name="articleDate" Text="{Binding Path=Date}" FontSize="14" Foreground="Gray"
Margin="5"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Border>
I have a feeling that the StackPanel just keeps on adding height forever. I think in this instance you'd be better off with a Grid layout within your Border. Put the Button StackPanel in one height defined row, and the ListBox in an autosizing * height row. This way Grid will stick within the confines of your form.

Categories

Resources