Trying to WPF Tab header, need to make 3 adjustments - c#

I want to alter the styling of some WPF tab headers. I would like to keep all the original styling of the tab headers, except for these three things -
Increase the height of the headers
Make the heights of each header the same. Normally the selected tab has a bigger height, I need the heights of both selected and unselected tabs to be the same.
Add a picture above the text on each header
Here is a before and after image of what I am looking to do -
Anyone know how to do this?

There you go, you can replace Stack panel with your nice images.
Update 1- in order to remove sizing effect when seelcting a tab you'll need to alter the TabItem style (header template is too light for it). Just get a StyleSnooper (http://blog.wpfwonderland.com/2007/01/02/wpf-tools-stylesnooper/) open it with VS2010 recompile it for .NET4, launch, navigate to TabItem and search for:
<Setter Property="FrameworkElement.Margin">
<Setter.Value>
<Thickness>
2,2,2,2</Thickness>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Margin" TargetName="Content">
<Setter.Value>
<Thickness>
2,2,2,2</Thickness>
</Setter.Value>
margins are the values you want to change to fix your 2. Then just put the modified version into the resources, so the app can pick it up. The style contains a lot of handy stuff you can tweak.
<Window x:Class="Immutables.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">
<Grid>
<TabControl TabStripPlacement="Left" x:Name="AreasTabControl" Margin="1">
<TabItem x:Name="AttributesTab">
<TabItem.HeaderTemplate>
<DataTemplate>
<Grid Width="100" Height="40">
<Border BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Left" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal">
<Rectangle VerticalAlignment="Top"
Width="5" Height="5" Fill="White" />
<Rectangle VerticalAlignment="Top"
Width="5" Height="5" Fill="Blue" />
<Rectangle VerticalAlignment="Top"
Width="5" Height="5" Fill="Red" />
</StackPanel>
</Border>
<TextBlock Margin="0,20,0,0">Go Russia!</TextBlock>
</Grid>
</DataTemplate>
</TabItem.HeaderTemplate>
</TabItem>
</TabControl>
</Grid>
</Window>

Related

Why does the application look different after launching than in designer?

I have a little question. I'm new to WPF and a strange thing happened to me. In the designer everything looks fine, but as soon as I start the application, a piece ,,cuts off"(via.photo) and it looks pretty bad. Could it be that the application is not responsive?
My XAML code:
<TabItem Header="TabItem"
Visibility="Hidden"
x:Name="Home_Page"
Background="{x:Null}"
BorderBrush="{x:Null}" Height="Auto"
Width="Auto"
>
<Border
Background="Black"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="1340"
Height="1100"
CornerRadius="20"
>
<Border
Background="White"
CornerRadius="20"
Height="700"
Width="500"
Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center"
>
<Grid
>
<TextBlock
Text="Welcome"
Width="200"
Height="200"
Foreground="Black"
FontSize="50" FontFamily="/Peel_App;component/Fonts/#Kashima Brush Demo"
>
</TextBlock>
</Grid>
</Border>
</Border>
</TabItem>
After what I edited app:
Your code has a few issues:
You're hardcoding the Margin values to position your controls. Instead, you should use proper panels (DockPanel, WrapPanel, and Grid). Use Margin property to set margin, not a position.
Use HorizontalAlignment and VerticalAlignment properties to position your elements, thus your UI would be more responsive and user-friendly.
To be able to view, how your window and its content would look like - try to set d:DesignHeght and d:DesignWidth properties on a window. Try to Google how to use them.
In the end, your code should look like following:
<TabItem Header="TabItem"
Visibility="Hidden"
x:Name="Home_Page"
Background="{x:Null}"
BorderBrush="{x:Null}"> <!-- Properties order is a bit confusing, it is better to order them by priority, or just alphabetically. -->
<Border Background="Black">
<Border Background="White"
CornerRadius="20"
Margin="0,0,93,118"> <!-- Should it have such values? Maybe just somenthing like Margin="0 0 90 120"? -->
<Grid>
<TextBlock Text="Welcome"
Foreground="Black"
FontSize="50"
FontFamily="/Peel_App;component/Fonts/#Kashima Brush Demo"/>
</Grid>
</Border>
</Border>
</TabItem>

XAML- how to set the height of a <TabControl> to a fixed value?

I have the following XAML markup, which I am using to display the GUI of my C# application:
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto"/>
<RowDefinition x:Name="RowDefinition2" Height="0.05*"/>
<RowDefinition x:Name="RowDefinition1" Height="*"/>
</Grid.RowDefinitions>
<TabPanel x:Name="headerPanel" Background="White" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" VerticalAlignment="Top"/>
<StackPanel Grid.Row="1" Orientation="Horizontal" FlowDirection="RightToLeft">
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" FlowDirection="LeftToRight" Height="30" VerticalAlignment="Top">
<Button Style="{DynamicResource NoChromeButton}" Click="backBtn_Click" Margin="0,0,0,0" HorizontalAlignment="Left" >
<Image Source="C:\...\arrow_left.png" Height="30" Width="40" />
</Button>
<Button Style="{DynamicResource NoChromeButton}" Click="RefreshBtn_Click" Margin="0,0,0,0" HorizontalAlignment="Left" >
<Image Source="C:\...\arrow_loop3.png" Height="30" Width="30" />
</Button>
<Button Style="{DynamicResource NoChromeButton}" Click="referThis" Margin="0,0,0,0" HorizontalAlignment="Left" HorizontalContentAlignment="Left" Height="30" Width="80">
<TextBlock>Refer Patient</TextBlock>
</Button>
</StackPanel>
<Border x:Name="contentPanel" BorderBrush="Green" BorderThickness="5" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="2" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
The above markup is nested inside the following structure at the top of the file:
<Window x:Class.... >
<Window.Resources>
<Style ...>
...
<Setter Property="Template">
<Setter.value>
<ControlTemplate TargetType="{x:Type TabControl}">
<!--(Above markup goes here) -->
Later in the file, I have the following markup:
</ControlTemplate>
</Setter.value>
</Setter>
</Style>
...
</Window.Resources>
<Grid Name = "grid">
<Image x:Name="Connected" Source="...\abc.png" Height="50" Width="50" Margin="750, 0, -5, 640"></Image>
<!-- A few more image tags here -->
<TabControl ... >
<!-- XML for each of the tab items & their content here -->
</TabControl>
</Grid>
</Window>
This XAML displays the following GUI:
As you can see from the image, the 'main content' of the page is overlapping the <StackPanel> where I have added buttons for the navigation, and other features of my application (back, refresh, etc).
I can resize the window, by dragging one of the corners, and adjust it so that the buttons and other features are all displayed correctly:
However, it is also possible to resize the window too much (i.e. make it too large), which causes too much white space to be displayed between these buttons and things, and also causes the images on the far right hand side to be moved to a different location than the one I had intended:
The images on the far right hand side of my application window are the ones displayed by the XAML markup in the third bit of code that I have copied into my question.
So, my question is- is there a way that I can 'fix' the size of the <StackPanel>, <Grid>, <Style> or header of the <TabPanel> where I am displaying the navigation buttons and other images so that they're not resized with the rest of the window when the user drags one of the corners of the window around?
I tried setting the Height property of the <TabControl> to a specific value (e.g. 50), but this caused the whole content of the <TabControl> to shrink to 50... i.e. all of the content of the window was then displayed in an area on the window that was only 50 pixels high...
Basically, I want the content that I have shown here to remain the same no matter how the user interacts with the application, and only the content displayed below this to be updated dynamically as the user interact with the application. Anyone have any suggestions?
Try setting the height of row 1 from 0.05* to Auto! That should solve the overlap issue.

My listview items are not showing up when setting a template for it

I have two templates, one for a textbox and one for a listview, both are just used to give them rounded corners instead of the default rectangle. My textbox needed the "ScrollViewer x:Name="PART_ContentHost" line in order to show text, but that doens't work for the listview. If I take out the Template for the listview the example listviewitem (stuff) will show up. Otherwise it won't and I can't see any other items I add in the code behind. What am I missing in the xaml to get this to work?
Here is my xaml below:
<!-- Design Templates to set the borders of the controls-->
<UserControl.Resources>
<ControlTemplate x:Key="TextBoxTemplate" TargetType="TextBox">
<Border BorderBrush="Black" BorderThickness="1,1,1,.5" CornerRadius="7">
<ScrollViewer x:Name="PART_ContentHost" ></ScrollViewer>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="ListViewTemplate" TargetType="ListView">
<Border BorderBrush="Black" BorderThickness=".5,1,1,1" CornerRadius="7">
</Border>
</ControlTemplate>
</UserControl.Resources>
<!-- Controls -->
<Grid Height="270" Width="400">
<StackPanel Width="390">
<TextBox Height="35" Name="InputTextbox" Template="{StaticResource TextBoxTemplate}" VerticalContentAlignment="Center" TextChanged="InputTextbox_TextChanged"></TextBox>
<ListView Height="235" Name="ResultsListView" Template="{StaticResource ListViewTemplate}" SelectionChanged="ResultsListView_SelectionChanged">
<ListViewItem Content="stuff"></ListViewItem>
</ListView>
</StackPanel>
</Grid>
Your ControlTemplate doesn't have a presenter associated with it. This is why you're not seeing any items. See this page for a working example of how to create a ListView.ControlTemplate:
MSDN: ListView ControlTemplate Example
and here's an updated xaml for your control template:
<ControlTemplate x:Key="ListViewTemplate" TargetType="ListView">
<Border BorderBrush="Black" BorderThickness=".5,1,1,1" CornerRadius="7">
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>

drawing a vertical line through a control

I have a UI like below :
Problem is at the moment the line splitting the name from the message is not visible unless the screen is filled (its basically a border on a custom control).
What I would like is for the parent control (stackpanel) to permanently have a line through it and not have to use the border on each MessageControl.
Is this possible?
Here is the code for the stackpanel :
<UserControl x:Class="ChatBoxWPF.ChatWindow"
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="402" d:DesignWidth="700" xmlns:my="clr-namespace:ChatBoxWPF" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<ScrollViewer>
<StackPanel Name="Messages" VerticalAlignment="Bottom"></StackPanel>
</ScrollViewer>
</UserControl>
UPDATE 1:
I tried this :
<ScrollViewer Name="scroll">
<StackPanel Name="Messages" VerticalAlignment="Bottom">
<Line StrokeThickness="1" X1="100" Y1="0" X2="100" Y2="{Binding ElementName=scroll, Path=ActualHeight}" />
</StackPanel>
</ScrollViewer>
Without the grid. It now sometimes shows in the designer, and other times not. And when run doesn't show at all. Do I need the grid?
A very blunt and simple approach:
<Grid>
<ScrollViewer>
<StackPanel Name="Messages" VerticalAlignment="Bottom"></StackPanel>
</ScrollViewer>
<Line StrokeThickness="0.5" X1="116" X2="116" Y1="0" Stroke="Gainsboro" Y2="{Binding ElementName=ToLevelControl, Path=ActualHeight}" />
</Grid>
I suggest you use a 2nd layer for you background - the 2nd layer could be a simple grid or anything you like:
<Grid>
<Grid ZIndex="0">
<anything I want!>
</Grid>
<ScrollViewer ZIndex="1">
<StackPanel Name="Messages" VerticalAlignment="Bottom">
</StackPanel>
</ScrollViewer>
</Grid>

Frame does not use Toolkit Transitions with ProgressBar inside Frame Template

I am switching to using a ProgressBar/Grid in the Frame of my application instead of via a Popup. I used this stack overflow post to get it working : Dynamic Progress bar In WP7
However, When using the example I no longer have page transitions. It will be hard for me to warrant the use of it if page transitions will not work properly. Is there something I'm missing? I tried setting the TargetType to "TransitionFrame", but that does not work properly and throws a XAML parse exception (for the namespace Microsoft.Phone.Controls.PhoneApplicationPages)
<ControlTemplate x:Key="LoadingIndicatorTemplate" TargetType="toolkit:TransitionFrame" >
<Grid x:Name="ClientArea">
<ContentPresenter />
<Grid x:Name="ProgressGrid" Background="Black" Opacity="0.85" Visibility="Collapsed" Loaded="ProgressGrid_Loaded">
<StackPanel x:Name="Loading" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10">
<TextBlock HorizontalAlignment="Center" Name="tbLoading" Text="Loading" Style="{StaticResource TextNormalStyle}" />
<ProgressBar Style="{StaticResource PerformanceProgressBar}" HorizontalAlignment="Center" Name="pbLoading" Width="400" Margin="10" IsIndeterminate="False" />
</StackPanel>
</Grid>
</Grid>
</ControlTemplate>
For using the Toolkit's TransitionFrame for page transitions as well as a custom ControlTemplate to show your progress bar, you must specify the TargetType for the ControlTemplate as toolkit:Transitionframe where toolkit is defined as:
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
The rest of the problem is that your ControlTemplate does not specify the template parts that the TransitionFrame requires. It requires two parts of type ContentPresenter named FirstContentPresenter and SecondContentPresenter. Change your ControlTemplate to the following to bring page transitions back:
<ControlTemplate x:Key="LoadingIndicatorTemplate" TargetType="toolkit:TransitionFrame">
<Grid x:Name="ClientArea">
<ContentPresenter x:Name="FirstContentPresenter" />
<ContentPresenter x:Name="SecondContentPresenter" />
<Grid x:Name="ProgressGrid"
Background="Black"
Opacity="0.85"
Visibility="Collapsed"
Loaded="ProgressGrid_Loaded">
<StackPanel x:Name="Loading"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="10">
<TextBlock x:Name="tbLoading"
HorizontalAlignment="Center"
Text="Loading"
Style="{StaticResource BoaTextNormalStyle}" />
<toolkit:PerformanceProgressBar x:Name="pbLoading"
HorizontalAlignment="Center"
Width="400"
Margin="10"
IsIndeterminate="False" />
</StackPanel>
</Grid>
</Grid>
</ControlTemplate>
NOTE: Jeff Wilcox's PerformanceProgressBar is now part of the Silverlight Toolkit, so you can use it directly as shown above.
If you're putting the progressbar on the frame but then animating the page then the animation won't include the progressbar.
Why not just put the progressbar on the page?

Categories