Question about WPF Resources/Styles & Scope - wpf

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

Related

Optionally apply multiple styles

Let's say I have a extremly simplified xaml as follows:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="converter" />
<Style TargetType="FrameworkElement" x:Key="maybeCollapsed">
<Setter Property="Visibility" Value="{Binding Collapsed, Converter={StaticResource converter}}" />
</Style>
</UserControl.Resources>
<StackPanel>
<Label FontWeight="Bold" Content="Header" x:Name="Header" />
<TextBox Text="Name" Style="{StaticResource maybeCollapsed}" />
<TextBox Text="{Binding Name1}" Style="{StaticResource maybeCollapsed}"/>
</StackPanel>
</UserControl>
How could I apply a second style to all elements that use the maybeCollapsed-style, setting the IsTabStopto False? I cannot do this in the style itself, as IsTabStop is not a member of FrameworkElements.
Use Control.IsTabStop instead
<Style TargetType="FrameworkElement" x:Key="maybeCollapsed">
<Setter Property="Visibility" Value="{Binding Collapsed, Converter={StaticResource converter}}" />
<Setter Property="Control.IsTabStop" Value="False" />
</Style>

WPF StackPanel content vertical alignment

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>

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>

WPF Creating a multi use control

I'm trying to create a WPF window that has a single control and 2 buttons displayed.
The control can be either a TextBox, ComboBox or Slider dependent on the type of object selected to launch this window.
Is it possible to do this or will I have to create a window with 3 conrtols and manipulate their position at runtime?
Regards
Tony
additions to original question
My implementation is as follows
<Window.Resources>
<Style TargetType="TextBox" x:Key="TextBoxTemplate">
<Setter Value="{Binding ElementName=MyWindow, Path=m_csValue}" />
</Style>
<Style TargetType="{x:Type ComboBox}" x:Key="ComboBoxTemplate">
<Setter Value="{Binding ElementName=MyWindow, Path=ItemsForSelection}" />
</Style>
<Style TargetType="{x:Type Slider}" x:Key="SliderTemplate">
<Setter Value="{Binding ElementName=MyWindow, Path=SliderDetail}" />
</Style>
<Style TargetType="{x:Type ContentControl}" x:Key="DisplayValues">
<!-- Default Template -->
<Setter Property="ContentTemplate" Value="{StaticResource TextBoxTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyWindow, Path=eType}" Value="{x:Static local:eTagDisplay.Text}">
<Setter Property="ContentTemplate">
<Setter.Value>
<ControlTemplate Template="{StaticResource TextBoxTemplate}" />
</Setter.Value>
</Setter>
</DataTrigger>
<!-- DataTrigger Binding="{Binding ElementName=MyWindow, Path=eType}" Value="{x:Static local:eTagDisplay.Combo}">
<Setter Property="ContentTemplate">
<Setter.Value>
<ControlTemplate Template="{StaticResource ComboBoxTemplate}" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=MyWindow, Path=eType}" Value="{x:Static local:eTagDisplay.Slider}">
<Setter Property="ContentTemplate">
<Setter.Value>
<ControlTemplate Template="{StaticResource SliderTemplate}" />
</Setter.Value>
</Setter>
</DataTrigger -->
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Width="267">
<StackPanel Name="TagEditor1">
<!-- Text="{Binding ElementName=MyWindow, Path=m_csValue}" / -->
<ContentControl Style="{StaticResource DisplayValues}" />
</StackPanel>
<Button Content="OK" Height="23" HorizontalAlignment="Left" Margin="12,154,0,0" Name="btnOK" VerticalAlignment="Top" Width="75" Click="OnClkOK" />
<Button Content="Cancel" Height="23" HorizontalAlignment="Left" Margin="180,154,0,0" Name="btnCancel" VerticalAlignment="Top" Width="75" Click="OnClkCancel" IsCancel="True" />
</Grid>
I'm getting an error 'System.Windows.Style' is not a valid value for the 'System.Windows.Controls.ContentControl.ContentTemplate' property on a setter. I don't know why this is happening.
My Binding is OK, i believe, as it picks up string OK....
I would do this with a <ContentControl> that has a different <ContentTemplate> depending on what type of control is needed.
You didn't specify how the control type is being passed to the window, so your DataTrigger bindings would probably look a bit different from mine, but this should give you the right idea:
<DataTemplate TargetType="{x:Type ContentControl}" x:Key="TextBoxTemplate">
<TextBox ... />
</DataTemplate>
<DataTemplate TargetType="{x:Type ContentControl}" x:Key="ComboBoxTemplate">
<ComboBox ... />
</DataTemplate>
<DataTemplate TargetType="{x:Type ContentControl}" x:Key="SliderTemplate">
<Slider ... />
</DataTemplate>
<Style x:Key="MyStyle" TargetType="{x:Type ContentControl}">
<!-- Default Template -->
<Setter Property="ContentTemplate"
Value="{StaticResource TextBoxTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding SomeBoundValue}" Value="ComboBox">
<Setter Property="ContentTemplate"
Value="{StaticResource ComboBoxTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding SomeBoundValue}" Value="Slider">
<Setter Property="ContentTemplate"
Value="{StaticResource SliderTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
...
<ContentControl Style="{StaticResource MyStyle}" />
You could also allow users to specify a Content for your UserControl or Window, and simply display it using a ContentPresenter bound to the Content. Something like this:
<UserControl.Template>
<StackPanel>
<ContentPresenter Content="{TemplateBinding Content}" />
<Button ... />
<Button ... />
</StackPanel>
</UserControl.Template>
then you could use it like this:
<local:MyUserControl>
    <TextBox ... />
</local:MyUserControl>
<local:MyUserControl>
<ComboBox ... />
</local:MyUserControl>
<local:MyUserControl>
<Slider ... />
</local:MyUserControl>
I think it is possible with single window.By exposing a property that sets visibilty based on some condition.
i.e textbox visibility is set to visibility.visible and combobox,slider visibilty is set to visibility.collpased.similarly if you want to have combobox visible you make that visible and others collapsed.similarly for slider.
example:
public Visibility TextboxVisibility
{
set
{
Visibility visible = value;
Textboxname.Visibility = visible ;
}
}
I hope this answers your question

WPF overriding setter properties

I'm using a style in my XAML for a label:
<Style x:Key="TreatEye" TargetType="Label">
<Setter Property="Foreground" Value="#d1d1d1" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="30" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Canvas>
<TextBlock x:Name="retreatText" Canvas.Left="80" Canvas.Top="5" FontSize="16" Text="Retreatment"/>
<TextBlock x:Name="bioinsulatorText" Canvas.Left="21" Canvas.Top="33" Text="Bioinsulator" />
<TextBlock x:Name="kxlText" Canvas.Left="21" Canvas.Top="70" Text="KXL Kit" />
</Canvas>
...
The problem I'm seeing is that the FontSize property of "reatreatText" is not overridden from the setter value of 30. This builds fine, but the end display has "reatreatText" as size 30. Why is this value not overridden?
Thanks in advance.
Sorry, but I tried your code inside Kaxaml and works as expected:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="TreatEye" TargetType="Label">
<Setter Property="Foreground" Value="#d1d1d1" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="30" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Canvas>
<TextBlock x:Name="retreatText" Canvas.Left="80" Canvas.Top="5" FontSize="16" Text="Retreatment"/>
<TextBlock x:Name="bioinsulatorText" Canvas.Left="21" Canvas.Top="33" Text="Bioinsulator" />
<TextBlock x:Name="kxlText" Canvas.Left="21" Canvas.Top="70" Text="KXL Kit" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<Label Style="{StaticResource TreatEye}">Ejemplo</Label>
</Grid>
</Page>
Result:
alt text http://img231.imageshack.us/img231/695/capture2p.png
You need to set a TemplateBinding on the TextBlock.
<TextBlock x:Name="retreatText"
Canvas.Left="80"
Canvas.Top="5"
FontSize="{TemplateBinding FontSize}"
Text="Retreatment"/>
That's how the setter properties get propogated to the internal structure.

Resources