When I create WPF applications, very quickly my XAML starts to bloat.
I then approach the XAML/style issue in a HTML/CSS way, looking for repetitive code and packing it into styles which I put into my Window.Resources section.
Is this the way others are doing it or is there some better way now in XAML? It just seems that the two blocks below only differ on two little words, it seems that I could put it in some kind of functional user control (this is a left-side menu) so that when I have 25 elements in my menu I could just have 25 lines of same with the names and perhaps the Click targets.
Or perhaps when I move this to MVVM this issue will take care of itself with DataBinding (it is currrently just a hard-coded prototype), so I can keep the names of the menu items in a collection in my ViewModel and it then creates the menu dynamically in an ItemsControl?
Or are bloated XAML files just a fact of life with WPF applications?
What kind of XAML styling strategies do you have when you create WPF applications?
Window.Resources (top of file):
<Window.Resources>
<Style x:Key="Link" TargetType="Button">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#555"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock TextDecorations="Underline"
Text="{TemplateBinding Content}"
Background="{TemplateBinding Background}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Current XAML:
<Expander HorizontalAlignment="Left" Header="File" VerticalAlignment="Top" ExpandDirection="Down" Width="200" Padding="2">
<Expander.Background>
<LinearGradientBrush>
<GradientStop Color="#bbb" Offset="0"/>
<GradientStop Color="#ccc" Offset="1"/>
</LinearGradientBrush>
</Expander.Background>
<Border CornerRadius="5">
<Border.Background>
<LinearGradientBrush>
<GradientStop Color="#ccc" Offset="0"/>
<GradientStop Color="#bbb" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Button Click="buttonClose_Click"
Style="{StaticResource Link}"
Margin="10 3 3 3"
Content="Close">
</Button>
</StackPanel>
</Border>
</Expander>
<Expander HorizontalAlignment="Left" Header="Customers" VerticalAlignment="Top" ExpandDirection="Down" Width="200" Padding="2">
<Expander.Background>
<LinearGradientBrush>
<GradientStop Color="#bbb" Offset="0"/>
<GradientStop Color="#ccc" Offset="1"/>
</LinearGradientBrush>
</Expander.Background>
<Border CornerRadius="5">
<Border.Background>
<LinearGradientBrush>
<GradientStop Color="#ccc" Offset="0"/>
<GradientStop Color="#bbb" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<Button Click="btnAppPage_Click"
Tag="CustomerAdd"
Style="{StaticResource Link}"
Margin="10 3 3 3"
Content="Create Customer"/>
</StackPanel>
</Border>
</Expander>
Simple: identify repetition and move it into a control. The control can have whatever properties necessary to compose the required variations at runtime. And it can be re-templated by virtue of being a control.
Also, you can identify repetitions and move them into resources. One resource can easily reference another.
Related
I am developing a WPF application and I'm using the standard WPF Datepicker.
Here is the XAML Code:
<DatePicker Grid.Column="0" Grid.Row="5" Margin="5,0,5,12"
x:Name="SendungDatePicker" SelectedDate="{Binding Path=ProduktionsDatum}"
ToolTip="{x:Static resx:MetaData.DateTooltip}" />
However, when I use it, the upper part of the calendar isn't displayed correctly:
As you can see, I can't see the month and year.
How can I solve this problem?
Thank you for your help
EDIT
I generated a template for the calendar style:
<Style x:Key="CalendarStyle1" TargetType="{x:Type Calendar}">
<Setter Property="Foreground" Value="#FF333333"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFE4EAF0" Offset="0"/>
<GradientStop Color="#FFECF0F4" Offset="0.16"/>
<GradientStop Color="#FFFCFCFD" Offset="0.16"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Calendar}">
<StackPanel x:Name="PART_Root" HorizontalAlignment="Center">
<CalendarItem x:Name="PART_CalendarItem" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Style="{TemplateBinding CalendarItemStyle}" Height="Auto" Width="Auto"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I update the height of the header of the calendar?
If you generate a style for CalendarItem then you will find that Height of Header Button is 20 and FontSize is 10.5. So you override the CalendarItem style and defined either the height of PART_HeaderTemplate or decrease the FontSize.
<Button x:Name="PART_PreviousButton" Grid.Column="0" Focusable="False" HorizontalAlignment="Left" Height="20" Grid.Row="0" Template="{StaticResource PreviousButtonTemplate}" Width="28"/>
<Button x:Name="PART_HeaderButton" Grid.Column="1" FontWeight="Bold" Focusable="False" FontSize="10.5" HorizontalAlignment="Center" Grid.Row="0" Template="{StaticResource HeaderButtonTemplate}" VerticalAlignment="Center"/>
<Button x:Name="PART_NextButton" Grid.Column="2" Focusable="False" HorizontalAlignment="Right" Height="20" Grid.Row="0" Template="{StaticResource NextButtonTemplate}" Width="28"/>
the problem is very simple, the header of your DatePicker is a Button. Surely you have somewhere put a style for your buttons where you specify a height for them.
Solution: if for your buttons you have set ... Height = 20 you must raise the height, Height = 25 Or try until you see that the header is not cut. That's why my friend cuts himself, because the button is not high enough.
I hope this helps someone who ever has this problem, since it's something that drove me crazy.
Since there is no Border.Effect property in Silverlight for Windows Phone, I managed to recreate a similar effect. What came up after editing the stile of a Pivot control is this:
As you can see the project is one of Visual Studio default templates.
With my custom style, the ItemsPanel is behind that black/gray gradient so, when you scroll the list, it's like items are disappearing.
<Style x:Key="PivotStyle1" TargetType="controls:Pivot">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:Pivot">
<Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Background="{TemplateBinding Background}" CacheMode="BitmapCache" Grid.RowSpan="3"/>
<Grid Grid.Row="1">
<ItemsPresenter x:Name="PivotItemPresenter" Margin="{TemplateBinding Padding}" VerticalAlignment="Top"/>
<Grid Height="50" VerticalAlignment="Top">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#66000000" Offset="0"/>
<GradientStop Offset="1"/>
<GradientStop Color="#19000000" Offset="0.523"/>
</LinearGradientBrush>
</Grid.Background>
</Grid>
</Grid>
<Grid Height="70" Grid.Row="0" VerticalAlignment="Top">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF1665CD" Offset="1"/>
<GradientStop Color="#FF5395EC"/>
</LinearGradientBrush>
</Grid.Background>
<Primitives:PivotHeadersControl x:Name="HeadersListElement"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem is that whenever I slide towards PivotItems the two Grid with a gradient background flicker. What could be the problem?
UPDATE: The flickering only appears when I navigate back to this page
Solved setting CacheMode to the Grid elements.
For Example:
<Grid Height="70" CacheMode="BitmapCache" Grid.Row="0" VerticalAlignment="Top">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF1665CD" Offset="1"/>
<GradientStop Color="#FF5395EC"/>
</LinearGradientBrush>
</Grid.Background>
<Primitives:PivotHeadersControl x:Name="HeadersListElement"/>
</Grid>
Rather than restyle the Pivot to add a background you'll probably find it much easier to create a single image to use as the page background and leave the Pivot background as transparent.
I'm trying to create a rounded end progress bar with a beveled border. I've got the progress bar looking like what I want but I'm having difficulty with making the border seemed beveled.
Can anyone help me out with this please?
An image of what I'm trying to get it to look like is here! Bevelled border
My current XAML code for the Window is as follows:
<Window x:Class="SplashDemo2.ProgressBarWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ProgressBarWindow" Height="100" Width="500">
<Window.Resources>
<Style x:Key="ProgressBarStyle" TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Border BorderBrush="#1D4276" BorderThickness="5"
CornerRadius="15" Padding="0">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,0.9" StartPoint="0.5,0">
<GradientStop Color="#FFEAEAEA" Offset="0.9"/>
<GradientStop Color="#FF646464"/>
</LinearGradientBrush>
</Border.Background>
<Grid x:Name="PART_Track" >
<Rectangle x:Name="PART_Indicator"
HorizontalAlignment="Left"
RadiusX="10" RadiusY="10">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,0.9" StartPoint="0.5,0">
<GradientStop Color="#FF226494" Offset="0.9"/>
<GradientStop Color="#FFEBEFFA"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ProgressBar Value="50" Width="380" Height="25"
Style="{StaticResource ProgressBarStyle}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Window>
Can anyone help me to get the border looking like the image? Many thanks.
It looks to me as though the main thing you're missing is the gradient brush on the border itself.
If you omit BorderBrush="#1D4276" and instead include something like the below, you'll be a lot closer:
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,0.9" StartPoint="0.5,0">
<GradientStop Color="#FFEBEFFA" Offset="0.9"/>
<GradientStop Color="#FF226494"/>
</LinearGradientBrush>
</Border.BorderBrush>
Is there a way that I can suppress the space to the left of a MenuItem's text?
alt text http://tanguay.info/web/external/extraSpaceMenus.png
Something like LeftAreaVisible="Collapsed" (pseudo-code) below:
<Menu DockPanel.Dock="Top">
<MenuItem
LeftAreaVisible="Collapsed"
Header="MVVM" ItemsSource="{Binding MvvmMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
</Menu>
Struck through the somewhat same problem. Also did you noticed that there is no separator visible between Create Models and Create Pages. My issue was horizontal separator not completely visible i.e. for Highlighted area there is no horizontal separator.
Here is how i fixed it:
<MenuItem Header="New"/>
<Separator>
<Separator.Style>
<Style TargetType="Separator">
<Setter Property="Margin"
Value="0,3" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Separator}">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Background="{StaticResource SeperatorBrush}"
Height="1"
SnapsToDevicePixels="true"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Separator.Style>
</Separator>
Also here is the brush.
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" x:Key="SeperatorBrush">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFF6F6F6" Offset="0.25" />
<GradientStop Color="#FFEAE8E8" Offset="0.25" />
<GradientStop Color="#FFDCD9D9" Offset="0.8" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
Brush is used to show the default appearance of Separator.
I have an Expander placed on a window with a blue background and I would like to make the button for the expander another color than the default (blue, which it is receiving from the window). When I modify the background property of the expander it changes the entire expander, header and all to the new color. However, I would like only the button itself to change. Could anyone point me to the right property that I am looking for?
Thank you
You not only have to retemplate the Expander ... you need to retemplate the ToggleButton within the Expander's template ... so that you can template bind the Background brush set on the Expander all the way down through the Expander's visuals and into the ToggleButton's visuals (using two TemplateBindings).
One thing that is helpful (at least for me) when you are learning how to modify the visuals of the WPF controls is to use the SimpleStyles as these are much easier to copy and modify ... than the full fledged, normal styles & templates.
To do this, open up Blend and go into the Asset Library (the bottom most tool) ... if you click on that you will see two sets of controls: System Controls and Simple Styles. Grab one of the controls (whichever one you want) from the Simple Styles and plunk it down on the design surface. Then, you can right click on it, Edit Control Parts (Template), and Edit a Copy. This will create a copy of the Simple Styles style and template ... which you can then (more easily) modify to your hearts content.
(I should note at this point that I would then modify that xaml (generated by Blend) in both Visual Studio and Blend ... flipping back and forth as necessary ... and taking advantage of the strengths of each: Blend for its WYSIWYG design surface ... and Visual Studio for its code editing and IntelliSense support.)
I have drafted up some quick xaml that does what you are asking and will include it below. You should be able to drop this xaml in Kaxaml or another loose xaml editor.
Hope this helps.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640"
Height="480"
>
<Page.Resources>
<LinearGradientBrush x:Key="NormalBrush" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#EEE" Offset="0.0"/>
<GradientStop Color="#CCC" Offset="1.0"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="NormalBorderBrush" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#CCC" Offset="0.0"/>
<GradientStop Color="#444" Offset="1.0"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="GlyphBrush" Color="#444"/>
<LinearGradientBrush x:Key="MouseOverBrush" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF" Offset="0.0"/>
<GradientStop Color="#AAA" Offset="1.0"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="PressedBrush" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#BBB" Offset="0.0"/>
<GradientStop Color="#EEE" Offset="0.1"/>
<GradientStop Color="#EEE" Offset="0.9"/>
<GradientStop Color="#FFF" Offset="1.0"/>
</LinearGradientBrush>
<ControlTemplate x:Key="newToggleButtonControlTemplate" TargetType="{x:Type ToggleButton}">
<Grid Background="{TemplateBinding Background}">
<Rectangle
x:Name="Rectangle"
Margin="0,0,0,0"
Fill="Transparent"
Stroke="{DynamicResource NormalBorderBrush}"
/>
<Path
x:Name="Up_Arrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{DynamicResource GlyphBrush}"
Data="M 0 0 L 4 4 L 8 0 Z"
/>
<Path
x:Name="Down_Arrow"
Visibility="Collapsed"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{DynamicResource GlyphBrush}"
Data="M 0 4 L 4 0 L 8 4 Z"
/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" Value="{DynamicResource MouseOverBrush}" TargetName="Rectangle"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Fill" Value="{DynamicResource PressedBrush}" TargetName="Rectangle"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Visibility" Value="Visible" TargetName="Down_Arrow"/>
<Setter Property="Visibility" Value="Collapsed" TargetName="Up_Arrow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="newExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" x:Name="ContentRow"/>
</Grid.RowDefinitions>
<Border
x:Name="Border"
Grid.Row="0"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2,2,0,0"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ToggleButton
Template="{DynamicResource newToggleButtonControlTemplate}"
Background="{TemplateBinding Background}"
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
/>
<ContentPresenter Grid.Column="1" Margin="4" RecognizesAccessKey="True" ContentSource="Header"/>
</Grid>
</Border>
<Border
x:Name="ExpandSite"
Grid.Row="1"
Visibility="Collapsed"
BorderThickness="1,0,1,1"
CornerRadius="0,0,2,2"
>
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Focusable="false"
/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter Property="Visibility" Value="Visible" TargetName="ExpandSite"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Page.Background>
<LinearGradientBrush EndPoint="0.997,0.996" StartPoint="0.002,0.058">
<GradientStop Color="#FF63A6DE" Offset="0"/>
<GradientStop Color="#FFC2DEF5" Offset="1"/>
</LinearGradientBrush>
</Page.Background>
<Grid x:Name="LayoutRoot">
<Expander
Style="{DynamicResource newExpanderStyle}"
Header="Expander"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="{DynamicResource NormalBrush}"
>
<Grid>
<Button Content="Hello World"/>
</Grid>
</Expander>
</Grid>
</Page>