VerticalScrollBarVisibility works when I define it inline like this:
<UserControl x:Class="TestScrollBar.MainPage"
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">
<UserControl.Resources>
<Style TargetType="TextBox" x:Key="EditListContainerContentMultiLineTwoColumn">
<Setter Property="AcceptsReturn" Value="True"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="300"/>
<Setter Property="IsReadOnly" Value="False"/>
<Setter Property="Margin" Value="0 0 0 20"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" Margin="10">
<StackPanel HorizontalAlignment="Left">
<TextBox Text="this is a test"
Style="{StaticResource EditListContainerContentMultiLineTwoColumn}"
VerticalScrollBarVisibility="Auto"
/>
</StackPanel>
</Grid>
</UserControl>
But when I put VerticalScrollBarVisibility in a style, it shows me a blank screen:
<UserControl x:Class="TestScrollBar.MainPage"
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">
<UserControl.Resources>
<Style TargetType="TextBox" x:Key="EditListContainerContentMultiLineTwoColumn">
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="AcceptsReturn" Value="True"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Height" Value="300"/>
<Setter Property="IsReadOnly" Value="False"/>
<Setter Property="Margin" Value="0 0 0 20"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" Margin="10">
<StackPanel HorizontalAlignment="Left">
<TextBox Text="this is a test"
Style="{StaticResource EditListContainerContentMultiLineTwoColumn}"
/>
</StackPanel>
</Grid>
</UserControl>
In WPF it works works fine.
How can I get VerticalScrollBarVisibility to work in a style?
It is not working because these properties are not dependency ones and cannot be applied with style. Unfortunately using the attached property on the ScrollViewer is also not working, because they are not template bound in the default style.
The only thing I can think of you can do is to create an attached behavior that is setting the required values on the text box and apply it through the style.
Related
I have below WPF UserControl:
<UserControl x:Class="myComponents.UI.TextBoxWithPlaceholder"
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"
xmlns:local="clr-namespace:pEp.UI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Loaded="UserControl_Loaded">
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:TextBoxWithPlaceholder}}"
Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="myCustomTextBox"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
Padding="5"
IsReadOnly="{Binding IsReadOnly}"
HorizontalAlignment="Stretch"
TextChanged="CustomTextBox_TextChanged"
GotFocus="CustomTextBox_GotFocus"
LostFocus="CustomTextBox_LostFocus"
Margin="5"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" />
<TextBlock Name="myPlaceholderTextBlock"
IsHitTestVisible="False"
Padding="5"
Text="{Binding Placeholder}"
HorizontalAlignment="Left"
Foreground="DarkGray"
Margin="5">
</TextBlock>
</Grid>
</UserControl>
Basically it is a TextBox with a placeholder.
Now from a WPF view I reuse this component by doing:
xmlns:ui="clr-namespace:myComponents.UI"
and then place it as a normal control:
<ui:TextBoxWithPlaceholder Name="myNewTextBox" IsReadOnly="{Binding IsReadOnly}"
Style="{StaticResource myTextBoxStyle}"
Placeholder="please, enter something here"/>
Now as you see above I set a custom style for it:
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="Foreground" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
Now in my "myNewTextBox" control I am trying to override some inherited properties for the controls named myCustomTextBox and myPlaceholderTextBlock such as Margin, Padding, Background, Foreground, BorderBrush, etc. but I have tried above style and it is not working. Also I have tried:
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Setter Property="{Binding Path=Margin, ElementName=myCustomTextBox}" Value="0" />
<Setter Property="{Binding Path=Padding, ElementName=myCustomTextBox}" Value="0" />
<Setter Property="{Binding Path=Margin, ElementName=myPlaceholderTextBlock }" Value="0" />
<Setter Property="{Binding Path=Padding, ElementName=myPlaceholderTextBlock }" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="{Binding Path=Background, ElementName=myCustomTextBox}" Value="{x:Null}"/>
<Setter Property="{Binding Path=Foreground, ElementName=myCustomTextBox}" Value="{x:Null}"/>
<Setter Property="{Binding Path=BorderBrush, ElementName=myCustomTextBox}" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
If you want to be able to set properties of the myCustomTextBox from view that consumes your TextBoxWithPlaceholder control, you should add dependency properties to the latter and bind to them in TextBoxWithPlaceholder.xaml and set them in the consuming view, e.g.:
<ui:TextBoxWithPlaceholder ....PlaceHolderMargin="10" />
TextBoxWithPlaceholder.xaml:
<TextBlock Name="myPlaceholderTextBlock"
...
Margin="{Binding PlaceHolderMargin,RelativeSource={RelativeSource AncestorType=UserControl}}">
I am afraid you cannot refer to ElementName=myPlaceholderTextBlock from a namescope outside the TextBoxWithPlaceholder control so trying to do this in a Style that's defined in a consuming view won't work.
This is a task that cries out for a Custom control and Visual States instead of a UserControl with Triggers. But if you must do this as a UserControl (and I don't blame you because that's a lot to learn at this stage) then here goes:
First of all, when you use ElementName it is supposed to refer to elements that the XAML processor has already seen, previously in the current UI being laid out. Not elements inside the control being styled. I don't see that approach working.
If you want the TextBox and TextBlock inside a TextBoxWithPlaceholder to use the properties of that outer control, you could bind them to it, inside your control's XAML. For example, to rewrite a small part of that binding the background.
<TextBox Name="myCustomTextBox"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
Background={Binding RelativeSource={RelativeSource.FindAncestor, AncestorType={x:Type ui:TextBoxWithPlaceholder}, Path=Background}}"
But if you truly want that nested TextBox ("myCustomTextBox") to use a style with triggers and its own dedicated property values, then what you might try is creating a Resources section inside your style that itself contains implicit styles for the TextBox and TextBlock Something like this
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Style.Resources>
<!-- Implicit style for TextBox should only apply to TextBoxes inside a TextBoxWithPlaceholder -->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Background Value="{x:Null}"/>
<Setter Property="Foreground" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</Trigger>
<Style.Triggers>
</Style>
</Style.Resources>
</Style>
I am using a TextBlock style.But it looks bad.
Am I missing code may have been written?
How can I solve this problem?
Here is code:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#FF353535"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="TextOptions.TextHintingMode" Value="Fixed"/>
<Setter Property="RenderOptions.ClearTypeHint" Value="Auto"/>
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Ideal"/>
<Setter Property="FontFamily" Value="Tahoma"/>
</Style>
TextFormattingMode.Ideal is far from Ideal :). You should use Display for small-to-medium text. More on text formatting here.
Here they are compared:
<Window
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:WpfApplication9" mc:Ignorable="d" x:Class="WpfApplication9.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#FF353535" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="TextOptions.TextHintingMode" Value="Fixed" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled" />
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="FontFamily" Value="Tahoma" />
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBlock>This text has TextOptions.TextRendering mode set to Display</TextBlock>
<TextBlock TextOptions.TextFormattingMode="Ideal">This text has TextOptions.TextRendering mode set to Ideal</TextBlock>
</StackPanel>
</Window>
I use a DataGrid (WPF 4.0) control. The style for it is placed in a ResourceDictionary and contains a nested Style element:
<Style x:Key="MyDataGridStyle" TargetType="{x:Type controls:DataGrid}">
<Setter Property="Background" Value="Black"/>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</Setter.Value>
</Setter>
</Style>
Here, only the Background style is applied. The CellStyle NOT.
It only works when I define the CellStyle directly inside the DataGrid element:
<DataGrid Style="{StaticResource MyDataGridStyle}">
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</DataGrid.CellStyle>
</DataGrid>
Any ideas why?
Update
It seems that there is a problem when mixing styles with PresentationFramework.Aero theme that I have referenced in my ResourceDictionary. If I remove the reference it works!
Doing it the way you suggest works fine for me, I'll paste the code that I used to test your style. (note that I added background = red so I could actually see if the style was being applied)
<Window x:Class="WpfApplication1.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="MyDataGridStyle" TargetType="{x:Type DataGrid}">
<Setter Property="Background" Value="Black"/>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Red"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<DataGrid Style="{StaticResource MyDataGridStyle}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Text}"/>
<DataGridTextColumn Binding="{Binding Tag}"/>
</DataGrid.Columns>
<DataGrid.Items>
<TextBlock Text="Item1" Tag="aa"/>
<TextBlock Text="Item2" Tag="bb"/>
<TextBlock Text="Item3" Tag="cc"/>
<TextBlock Text="Item4" Tag="dd"/>
</DataGrid.Items>
</DataGrid>
</Window>
the results are
In WPF is there container like an HTML div (where this is easy), where I could target all textblocks within that container? So I do not have to specify the style on every textblock?
I have a complex canvas and in just a region I would like to target the textblocks.
Something to the effect of this (where something other than StackPanel that would work as a style targeting container):
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="FontFamily" Value="Arial"></Setter>
</Style>
</StackPanel.Resources>
<TextBlock Canvas.Left="87" Canvas.Top="210">
mytext1
</TextBlock>
<TextBlock Canvas.Left="87" Canvas.Top="232">
mytext2
</TextBlock>
<TextBlock Canvas.Left="87" Canvas.Top="254">
mytext2
</TextBlock>
</StackPanel>
So if I try a grid the canvas coordinates get ignored and my textblock appears at the top of the canvas.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Canvas Width="500" Height="500">
<Grid>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"></Setter>
</Style>
</Grid.Resources>
<TextBlock Text="MyTextBlock1" Canvas.Left="300" Canvas.Top="300">
</TextBlock>
</Grid>
</Canvas>
In this case you are using the canvas coordinates to give 87 spacing on the left and 22 spacing between tops of elements. The StackPanel is already laying out the items one after another. You just need to set the margins for your textblocks
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="FontFamily" Value="Arial"></Setter>
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="87,4, 0, 4" />
</Style>
</StackPanel.Resources>
<TextBlock>mytext1</TextBlock>
<TextBlock>mytext2</TextBlock>
<TextBlock>mytext3</TextBlock>
</StackPanel>
To answer your question you can use a Grid control (or Canvas or any other element) wherever you wish to isolate a Resources section. Grid does not perform any layout.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="FontFamily" Value="Arial"></Setter>
</Style>
</StackPanel.Resources>
<TextBlock>
mytext1
</TextBlock>
<Canvas>
<Canvas.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="FontFamily" Value="Times"></Setter>
</Style>
</Canvas.Resources>
<TextBlock Canvas.Left="87" Canvas.Top="210">mytext2</TextBlock>
<TextBlock Canvas.Left="87" Canvas.Top="232">mytext2</TextBlock>
</Canvas>
</StackPanel>
I am beginner on WPF and need your help.
Problem:
I have 4 buttons on the form and need to apply 2 different style on pair of 2 buttons.
Is there any way we can achive this ?
please provide me sample if possible...
Thanks in advance...
You can define named styles and then assign them explicitly to any controls as you wish.
Here is a primer for styling buttons: Getting Started with WPF : Button Control Part 2 – Basic Styling
And here is an example:
<Window x:Class="WpfButtonStyling.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="400">
<Window.Resources>
<Style x:Key="ButtonStyle1"
TargetType="{x:Type Button}">
<Setter Property="Foreground"
Value="Red" />
<Setter Property="Margin"
Value="10" />
</Style>
<Style x:Key="ButtonStyle2"
TargetType="{x:Type Button}">
<Setter Property="Foreground"
Value="Blue" />
<Setter Property="Margin"
Value="10" />
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button x:Name="FirstButton"
Content="First!"
Style="{StaticResource ButtonStyle1}"/>
<Button x:Name="SecondButton"
Content="Second"
Style="{StaticResource ButtonStyle2}" />
</StackPanel>
</Grid>
</Window>
If someone want to write Style directly in Button, write like below:
<Button>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="TimesNewRoman" />
<Setter Property="FontSize" Value="50"/>
<Setter Property="Background" Value="Green"/>
</Style>
</Button.Style>
</Button>
Use this Code For different styles for different buttons or any other
<Window x:Class="WpfApplication1.MainWindow"
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"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Window.Resources>
**<Style x:Key="a" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="FontSize" Value="50"/>
<Setter Property="Background" Value="Indigo"/>
</Style>
<Style x:Key="b" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="16"/>
</Style>
<Style x:Key="c" TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="TimesNewRoman" />
<Setter Property="FontSize" Value="50"/>
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<TextBlock Margin="26,41,39,0" Style="{StaticResource a}" Height="100" VerticalAlignment="Top">TextBlock with Style1</TextBlock>
<TextBlock Margin="26,77,39,0" Height="32" VerticalAlignment="Top">TextBlock with no Style</TextBlock>
<TextBlock Margin="26,105,67,96" Style="{StaticResource b}">TextBlock with Style2</TextBlock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="26,170,-26,0">
<Button Style="{StaticResource c}">
<Bold >Styles</Bold></Button>
<Button Style="{StaticResource c}">are</Button>
<Button Style="{StaticResource c}">cool</Button>
</StackPanel>
</Grid>
here i declaring the style for both textBlock and button.Use this one..