WPF StackPanel content vertical alignment - wpf

Is there a way in XAML to say that I want to center-align vertically all components inside a horizontal-oriented StackPanel?
I achieve the desired result with the below XAML:
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"/>
<Button VerticalAlignment="Center"/>
<TextBox VerticalAlignment="Center"/>
<Button VerticalAlignment="Center"/>
<TextBlock VerticalAlignment="Center"/>
</StackPanel>
But I need to repeat the VerticalAlignment="Center" for each control separately.
Is there a way to declare on the StackPanel level something like below?
<StackPanel Orientation="Horizontal" VERTICALCONTENTALIGNMENT="Center">
<TextBlock/>
<Button/>
<TextBox/>
<Button/>
<TextBlock/>
</StackPanel>

Put the StackPanel inside a Grid and set VerticalAlignment="Center" on the StackPanel
<Grid>
<StackPanel VerticalAlignment="Center">
...
</StackPanel
</Grid>

You can define style for StackPanel with Trigger which sets VerticalAlignment of all children:
<Style x:Key="HorizontalStackPanel" TargetType="{x:Type StackPanel}">
<Setter Property="Orientation" Value="Horizontal" />
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center" />
</Trigger>
</Style.Triggers>
</Style>
And apply this style:
<StackPanel Style="{StaticResource HorizontalStackPanel}">
<TextBlock />
<Button />
<TextBox />
<Button />
<TextBlock />
</StackPanel>
It works for me.
The whole code:
<Window x:Class="WpfApplication11.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>
<Style x:Key="HorizontalStackPanel" TargetType="{x:Type StackPanel}">
<Setter Property="Orientation" Value="Horizontal" />
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel Style="{StaticResource HorizontalStackPanel}">
<TextBlock Text="One"/>
<Button Content="Two"/>
<TextBox Text="Three"/>
<Button Content="Four"/>
<TextBlock Text="Five"/>
</StackPanel>
</Grid>
</Window>

Define a style like this;
<Style x:Key="StackHorizontal" TargetType="StackPanel">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>

Just use this:
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock/>
<Button/>
<TextBox/>
<Button/>
<TextBlock/>
</StackPanel>

Related

Change Style of a child element in a CustomControl

I have a CustomTextBox as follows:
<TextBox x:Class="StackOverflow.CustomUserControl.CustomTextBoxView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="MainTextBox"
mc:Ignorable="d">
<TextBox.Template>
<ControlTemplate>
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
Margin="0,0,0,5"
Panel.ZIndex="1" />
<Border CornerRadius="2"
Name="BorderToChange"
BorderThickness="0,0,0,3.7"/>
<TextBlock Text="{Binding ElementName=MainTextBox, Path=HintText}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground"
Value="Transparent" />
<Setter Property="Margin"
Value="0,0,0,3" />
<Setter Property="VerticalAlignment"
Value="Bottom" />
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</ControlTemplate>
</TextBox.Template>
I use this CustomTextBox as follows:
<customUserControl:CustomTextBoxView Width="50"
Height="50"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Text="{Binding Mode=TwoWay, Path=Period, UpdateSourceTrigger=PropertyChanged}"/>
Is there a way I can change the property BorderThickness of the Border element named "BorderToChange" inside the ControlTemplate of my CustomTextBox when using it? I have try the following, but it didn't work:
<customUserControl:CustomTextBoxView Width="50"
Height="50"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="35"
Text="{Binding Mode=TwoWay, Path=Period, UpdateSourceTrigger=PropertyChanged}">
<customUserControl:CustomTextBoxView.Resources>
<Style TargetType="{x:Type customUserControl:CustomTextBoxView}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="10"></Setter>
</Style>
</Style.Resources>
</Style>
</customUserControl:CustomTextBoxView.Resources>
</customUserControl:CustomTextBoxView>
Use a {TemplateBinding} in the template:
<Border CornerRadius="2" Name="BorderToChange" BorderThickness="{TemplateBinding BorderThickness}"/>
...and specify a default value:
<TextBox x:Class="..." BorderThickness="0,0,0,3.7"> ...
You can then simply set the BorderThickness property of the control to override the default value:
<customUserControl:CustomTextBoxView ... BorderThickness="1" ... />

How to display multiple images as thumbnails in xaml

I am trying to create xaml page in silver light application. How to create a page like this, I have created a xaml page, but I can't create like this, my code is...
<UserControl x:Class="XXX.Views.Attachment.AttachmentViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:xxx.Controls"
xmlns:local2="clr-namespace:xxx.Controls"
xmlns:XXX="clr-namespace:xxx.Controls;assembly=XXX.SL"
xmlns:baseconverters="clr-namespace:System.Windows.Converters;assembly=XXX.SL"
mc:Ignorable="d"
d:DesignHeight="800" FontFamily="{StaticResource MainFont}" d:DesignWidth="350">
<Grid x:Name="LayoutRoot" >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style x:Key="HeaderStyle" TargetType="TextBlock" >
<Setter Property="Margin" Value="5"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="20"/>
</Style>
</Grid.Resources>
<TextBlock Text="attachments" Style="{StaticResource HeaderStyle}"/>
<Rectangle Height="2" VerticalAlignment="Bottom" Fill="{StaticResource ColorDefaultGray}" Margin="0,40,0,5"/>
<ListView Grid.Row="1" x:Name="FileListItemsControl" VerticalAlignment="Top" Height="200" Margin="20" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Thumbnail, Converter={StaticResource ThumbnailToImageConverter}}" Height="150" Width="300" />
<TextBlock Text="{Binding FileName}" Style="{StaticResource BodyTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</UserControl>
it shows the name ListView does not exist, please find the attached image.
ListView is not found because it is not part of the version of Silverlight you are using.
You can apply a style to a ListBox control and replacing the item panel template with a WrapPanel from silverlight Toolkit.
Here is a Resource Dictionary with some styles that can be applied to ListBox controls to get he result you displayed in your attached image.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<!--Wrapping ListBox Styles-->
<Style x:Key="StretchedItemContainerStyle" TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<Style x:Key="ListBox_StretchedItemStyle" TargetType="ListBox">
<Setter Property="ItemContainerStyle" Value="{StaticResource StretchedItemContainerStyle}"/>
</Style>
<Style x:Key="ListBox_HorizontalWrapStyle" TargetType="ListBox">
<Setter Property="ItemContainerStyle" Value="{StaticResource StretchedItemContainerStyle}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" Margin="0"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer VerticalScrollBarVisibility="Auto" BorderBrush="{x:Null}" >
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBox_VerticalWrapStyle" TargetType="ListBox">
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate >
<toolkit:WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<!--End Wrapping ListBox Styles-->
</ResourceDictionary>
With the ListBox_HorizontalWrapStyle you just need to apply it to your target ListBox control
<ListBox Grid.Row="1" x:Name="FileListItemsControl" VerticalAlignment="Top" Height="200" Margin="20" Style={StaticResource ListBox_HorizontalWrapStyle} >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Thumbnail, Converter={StaticResource ThumbnailToImageConverter}}" Height="150" Width="300" />
<TextBlock Text="{Binding FileName}" Style="{StaticResource BodyTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Applying a style to all the TextBlocks that are children of StackPanel

Suppose I have a layout as below:
<Grid>
<TextBlock........ />
<StackPanel>
<TextBlock ...../>
<!--Other Elements-->
</StackPanel>
<TextBlock........ />
<StackPanel>
<TextBlock ...../>
<!--Other Elements-->
</StackPanel>
<TextBlock........ />
<StackPanel>
<TextBlock ...../>
<!--Other Elements-->
</StackPanel>
</Grid>
Now I want to apply a style like below to all the textblocks that are children of StackPanel in above mentioned layout.
<Style TargetType={x:Type TextBlock}>
<Setter Property="FontSize" Value="20" />
<Style>
First Method:
Example 1:
<Window.Resources>
<Style TargetType="StackPanel">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20" />
</Style>
</Style.Resources>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock/>
</StackPanel>
<StackPanel>
<TextBlock />
</StackPanel>
Example 2: if you want textblock-stackpanel in particular grid
<Window.Resources>
<Style x:Key="Textblockstyle" TargetType="Grid">
<Style.Resources>
<Style TargetType="StackPanel">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="Green"/>
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
</Window.Resources>
<Grid>
<StackPanel Height="100" VerticalAlignment="top" Width="100">
<TextBlock Text="Another Grid" />
</StackPanel>
<Grid Style="{StaticResource Textblockstyle}">
<StackPanel Height="100" HorizontalAlignment="Left" Width="100">
<TextBlock Text="Textblock1" />
</StackPanel>
<StackPanel Height="100" HorizontalAlignment="Right" Width="100">
<TextBlock Text="Textblock2"/>
</StackPanel>
</Grid>
</Grid>
Second Method :Give style name to every textblock in stackpanel
<Window.Resources>
<Style x:Key="Textblockstyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="Green"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Text="abc" Style="{StaticResource Textblockstyle}"/>
<!--Other Elements-->
</StackPanel>

Change TabItem.Header, when selected, from image to text

I have bumped into a problem to which I am seeking the solution.
I have a tabControl with styles added to it.
I want to display only images on each TabItem.Header and when that tab is selected then hide the image from header and display text (the other, inactive headers will be showing images).
Can anybody provide any help?
<Window.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Borderer" Background="#FF777777" Height="70" Width="90">
<ContentPresenter x:Name="ContentTabItem" ContentSource="Header" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="#FF000000" />
<Setter TargetName="Borderer" Property="Background" Value="WhiteSmoke" />
<Setter Property="Header" >
<Setter.Value>
<Grid>
<ContentPresenter ContentSource="Tag" />
</Grid>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl Height="189" HorizontalAlignment="Left" Margin="94,123,0,0" Name="tabControl1" VerticalAlignment="Top" Width="500">
<TabItem Name="tabItem1" IsSelected="True" >
<TabItem.Tag>
<TextBlock Text="blab lab la" />
</TabItem.Tag>
<TabItem.Header>
<Image Source="images/img1.png" Width="35" Height="35" />
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Name="aaa" />
</Grid>
</TabItem.Content>
</TabItem>
<TabItem >
<TabItem.Tag>
<TextBlock Text="la lab blab" />
</TabItem.Tag>
<TabItem.Header>
<Image Source="images/img2.png" Width="35" Height="35" />
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Name="bbb" />
</Grid>
</TabItem.Content>
</TabItem>
</TabControl>
</Grid>
You can actually do this without replacing the whole ControlTemplate on the TabItem. You can just alter the TabItem's HeaderTemplate when the TabItem is selected, making your Style a lot shorter:
<DataTemplate x:Key="SelectedHeaderTemplate" >
<ContentControl Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem},
Path=Tag}" />
</DataTemplate>
<Style TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="HeaderTemplate" Value="{StaticResource SelectedHeaderTemplate}" />
</Trigger>
</Style.Triggers>
</Style>

Question about WPF Resources/Styles & Scope

i am just beginning WPF and wonder why this works
<Window ...>
<Window.Resources>
<Style x:Name="buttonStyle">
<Style.Setters>
<Setter Property="Button.FontWeight" Value="Bold" />
<Setter Property="Button.Foreground" Value="Aqua" />
</Style.Setters>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button ... Style="{StaticResource buttonStyle}" />
</StackPanel>
</Grid>
</Window>
but this fails,
<Window ...>
<Window.Resources>
<Style x:Name="buttonStyle">
<Style.Setters>
<Setter Property="Button.FontWeight" Value="Bold" />
<Setter Property="Button.Foreground" Value="Aqua" />
</Style.Setters>
</Style>
</Window.Resources>
<Grid>
<StackPanel ...>
<StackPanel.Resources>
<Style x:Name="buttonStyle2">
<Setter Property="Button.Foreground" Value="Red" />
</Style>
</StackPanel.Resources>
<Button ... Style="{StaticResource buttonStyle}" />
<Button ... Style="{StaticResource buttonStyle2}" />
</StackPanel>
</Grid>
</Window>
the error is
The resource "buttonStyle2" could not be resolved
The resource "buttonStyle" could not be resolved
buttonStyle resolves ok in the 1st code (without the 2nd button)
arr... my bad, i should be using x:Key not x:Name

Resources