Writing a "Progress Pie" style for WPF ProgressBar - c#

I'm trying to write a WPF style for ProgressBar that turns the standard bar in a "Progress pie".
This is what I've tried so far:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Style x:Key="ProgressPie" TargetType="{x:Type ProgressBar}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid x:Name="TemplateRoot" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="PART_Track"
Fill="{TemplateBinding Background}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<ed:Arc x:Name="PART_Indicator"
ArcThickness="1"
ArcThicknessUnit="Percent"
Fill="{StaticResource SomeStaticBrush}"
ToolTip="{TemplateBinding Value}"
EndAngle="{TemplateBinding Value}"/>
<ed:Arc x:Name="OuterPieBorder"
ArcThickness="{TemplateBinding BorderThickness}"
ArcThicknessUnit="Pixel"
Stroke="{TemplateBinding BorderBrush}"
StartAngle="0"
EndAngle="360"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="0"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Unfortunately I have at least a couple problems:
It seems that the width of PART_Indicator is bound to the Value of the template. How come? I haven't written anything to do so.
I can't find a simple way to position PART_Indicator so that the center of the pie coincides with the center of PART_Track; any suggestions?

It seems that the width of PART_Indicator is bound to the Value of the template. How come? I haven't written anything to do so.
That is how templates works :) see this for more explanations.
Regarding your second question I dont see any "magic answer" (I guess there isnt), but this answer might help you.
If you can read french, or you trust google translate, there is this one as well which does what you want, and seems pretty complete.

Related

Why WPF cut components when I run the program

I'm doing a WPF program, with some textbox, labels and buttons.
Using the XAML designer, it works fine, the components are shown as they should. But when I run the program, it seems that the window shortens and cut some components in the sides.
Why are the components (button and labbel) being cut only when I run the program?
Here's the Xaml code of the 2 affected components:
<Window x:Class="XML_Edit.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"
xmlns:local="clr-namespace:XML_Edit"
mc:Ignorable="d"
Title="XML_Edit" Height="380" Width="470" ResizeMode="NoResize" Icon="Imagenes/xml.png">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4" />
</Style>
</Style.Resources>
</Style>
<Style TargetType="{x:Type TextBox}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4" />
</Style>
</Style.Resources>
</Style>
</Window.Resources>
<Grid Background="#FF363944">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="49*"/>
<ColumnDefinition Width="183*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="80"/>
<RowDefinition Height="80"/>
<RowDefinition Height="45"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<!-- Components -->
<Button Name="btCambiarContenido" Grid.Row="4" Content="Cambiar Contenido" VerticalAlignment="Center" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="26,80,0,16" Height="36" Width="135" Click="BtCambiarContenido_Click" TabIndex="5" Background="{x:Null}" BorderBrush="#FF4EB8CE" FontSize="14" Grid.ColumnSpan="2" Foreground="#FF4EB8CE"/>
<Label Name="lbSeleccionarRuta" Grid.Row="1" ToolTip="Seleccionar archivo" Height="32" Width="32" Margin="293.333,32,41,16" MouseDown="LbSeleccionarRuta_MouseDown" Grid.Column="1">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Imagenes/folder_azul.png"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Imagenes/folder_gris.png"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
They are shown fine in the WPF editor:
But they fet cut when I run the program:
You're setting your Button height to 36 pixels and giving it a margin of 26,80,0,16. This is effectively telling the layout manager that you want 36+80+16=132 pixels reserved to accommodate that button in row 4.
Meanwhile, in your grid layout you're specifying the rows 0-3 to have 15+80+80+45 pixels reserved. Combined with the 132 you're reserving for your button that's 352. But you're also explicitly setting your window height to 380, and that has to accommodate not just your 352 client area pixels but also the border and caption (as an experiment set your WindowStyle to None to remove the border and caption bar and you'll see your full control appear again). The layout manager has to cut pixels somewhere, and since row 4 is the only one you've specified with a "*" that's where they get cut, so the top and bottom of your button get cut as well. The reason you're not seeing this in designer is because it's using different theming to your OS, which is taking into account things like screen DPI, Windows theme settings, accessibility and several other things; the caption bar in designer is simply a bit smaller.
Issues like this are one of the many reasons you have to be careful doing explicit pixel layouts in WPF, and why you have to be especially careful with margins.

WPF Setting scrollbar thumb size with style removes all style from control

I'm attempting to use the following code suggested to change the minimum thumb size for scrollbars to not be unreasonably small. All of the instances using StaticResource say "The resource "x" cannot be resolved." I've attempted to change it to DynamicResource which removes the errors and properly runs but instead I get something that barely looks like a scrollbar. I've tried another suggestion here and I got a similar result of something that barely looks like a scrollbar. I should also note that I'm relying on the scrollbar that comes implemented in the textbox class so I don't have the luxury of extending the scrollbar like others have suggested.
How would I go about using styles to fix the minimum thumb size of my textbox scrollbar without completely destroying the style of the control?
The following code was gotten from this Microsoft page.
<Style TargetType="ScrollBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Name="Bg"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="{DynamicResource
{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
<RowDefinition Height="0.00001*"/>
<RowDefinition MaxHeight="{DynamicResource
{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
</Grid.RowDefinitions>
<RepeatButton Style="{StaticResource ScrollBarButton}"
IsEnabled="{TemplateBinding IsMouseOver}"
Height="18"
Command="ScrollBar.LineUpCommand"
Content="M 0 4 L 8 4 L 4 0 Z" />
<Track Name="PART_Track"
IsDirectionReversed="true"
Grid.Row="1"
Grid.ZIndex="-1">
<Track.Resources>
<!-- Set the Thumb's minimum height to 50.
The Thumb's minimum height is half the
value of VerticalScrollBarButtonHeightKey. -->
<sys:Double
x:Key="{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}">
100
</sys:Double>
</Track.Resources>
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource VerticalScrollBarPageButton}"
Command="ScrollBar.PageUpCommand"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource VerticalScrollBarPageButton}"
Command="ScrollBar.PageDownCommand"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb/>
</Track.Thumb>
</Track>
<RepeatButton
Grid.Row="2"
Style="{StaticResource ScrollBarButton}"
Height="18"
Command="ScrollBar.LineDownCommand"
Content="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="PART_Track"
Property="IsEnabled" Value="false">
<Setter TargetName="PART_Track"
Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The following is a basic example of the window.
<Window x:Class="TriggersNotepad.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"
xmlns:local="clr-namespace:TriggersNotepad"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Trigger's Notepad" Height="350" Width="525" ResizeMode="CanResizeWithGrip">
<Window.Resources>
Code above...
</Window.Resources>
<TextBox AcceptsReturn="True" UseLayoutRounding="False" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" BorderThickness="0"/>
</Window>
There are two ways: the hard one, and the easy one.
Let's start with the hard one, which, in its turn, is more flexible. In order to tweak the default style of a control, you should copy the whole style, including all the resources it refers to. You don't need to dig in MSDN for a style, just use Visual Studio:
In XAML Design window, select a control you want to tweak. In your case, you should create a <ScrollBar/> and select it in the designer.
In the main menu, click Format – Edit Style – Edit a Copy... – Apply To All – OK.
Modify the style as needed.
And now the easy one:
Create a new style that is BasedOn a default style.
Override the resources that are used by the default style by putting them in the <Style.Resources>.
Here is the example:
<Style TargetType="{x:Type ScrollBar}" BasedOn="{StaticResource {x:Type ScrollBar}}">
<Style.Resources>
<sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}">42</sys:Double>
<sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">42</sys:Double>
<sys:Double x:Key="{x:Static SystemParameters.HorizontalScrollBarHeightKey}">42</sys:Double>
<sys:Double x:Key="{x:Static SystemParameters.HorizontalScrollBarButtonWidthKey}">42</sys:Double>
</Style.Resources>
</Style>
And here is a screenshot of what you get:
Hope this helps!

Why are some TemplateBinding values not shown in designer but others are? [with repro code]

I've got an odd situation:
Following sample code replaces the Content of the window, uses the setter's background color and provides a stack panel with two labels. One for the background and one for the title.
The thing is, that they during design time
<Label Content="{TemplateBinding Background}" /> does perfectly show the background value however
<Label Content="{TemplateBinding Title}" /> does that only when running the app.
What is the difference here?
I've played around with the TargetType (by setting it to MainWindow, no effect)
This is the full sample:
<Window x:Class="TBinding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="350" Width="525">
<Window.Style>
<Style TargetType="Window">
<Setter Property="Background" Value="LawnGreen" />
<Setter Property="Title" Value="The title of this window" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<StackPanel Margin="50" Background="{TemplateBinding Background}">
<Label Content="{TemplateBinding Background}" />
<Label Content="{TemplateBinding Title}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
</Window>
Found on connect: https://connect.microsoft.com/VisualStudio/feedback/details/770067/wpf-designer-not-sho
Designer creates a proxy for Window classes and not the Window itself. The substitute does not fully reflect all properties therefore has limited functionality.
This issues occurs in VS2012 as well in VS2013.

Making tab header flexible to header text on WPF

I'm new to the WPF stuff around and I tried restyling a TabItem myself.
As you people can see the tabs are filling the window's whole width. Unlike my original purpose which I actually wanted to make the tabs width is based on the text inside of it. Like the original style, only redesigned.
My style in code:
<Style x:Key="ZoidTab" TargetType="{x:Type TabItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate x:Name="ZoidTemplate" TargetType="{x:Type TabItem}">
<Border Width="Auto" Height="Auto">
<Grid x:Name="grid">
<Polygon
Fill="Turquoise"
Points="0,1 0.05,0 0.95,0 1,1"
Stretch="Fill"
Margin="0,0,0,0"
/>
<ContentPresenter x:Name="tabContent" HorizontalAlignment="Center" ContentSource="Header" VerticalAlignment="Center" TextElement.Foreground="#FFFFFFFF"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="12pt"/>
</Style>
I'd like to know what is it that I must fix to get the width right... Thank you.
The problem is that your Grid doesn't have a ColumnDefinitions section to limit the size of the one and only column. Modify it to look like this:
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
...

WPF - how to determine why this XAML style code is not working?

Any advice how to fault find to work out why the Grid.Resources styles in this XAML is not making any difference it seems to the end result?
Note I'm using Charting from the WPFToolkit so to adjust how a chart looks it seems one has to apply the style areas (suggested by someone on the forum).
So my question is generically, noting I'm trying to adjust the look of a 3rd party graph, how can I debug/fault-find to understand what's going wrong? Is there a debugging trick? For example when I increased the BorderThickness to 30 I couldn't see a difference. What I'm really after is the equivalent of FireBug for HTML/CSS, which lets you understand/view what CSS is being applied to what elements.
EDIT: So I really (I think) want to be able to walk the object tree of the graph, and referring back to the template changes put in the Grid.Resources area, see why they didn't occur.
<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:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" mc:Ignorable="d" x:Name="Splash" x:Class="MyInternetUsage.SplashWindow"
Title="SplashWindow" Height="421" Width="570">
<DockPanel>
<StackPanel VerticalAlignment="Top" DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="Configure" HorizontalAlignment="Left" Margin="0" Width="78" VerticalAlignment="Center" Name="ConfigureButton" Click="ConfigureButton_Click" />
<Button Content="Start" Name="StartButton" Width="78" Click="StartButton_Click" />
<Button Content="Stop" Name="StopButton" Width="78" Click="StopButton_Click" />
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Summary" Grid.Column="0"/>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext"
Width="5" Background="#FFBCBCBC"/>
<Grid Grid.Column="2">
<Grid.Resources>
<Style x:Key="GooglePolylineStyle" TargetType="Polyline">
<Setter Property="StrokeThickness" Value="30"/>
</Style>
<Style x:Key="GoogleLineDataPointStyle" TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Background" Value="#0077CC" />
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="30"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LineDataPoint">
<Grid x:Name="Root" Opacity="1">
<ToolTipService.ToolTip>
<StackPanel Margin="2,2,2,2">
<ContentControl Content="{TemplateBinding IndependentValue}"
ContentStringFormat="{}{0:MMMM d, yyyy}"/>
<ContentControl Content="{TemplateBinding DependentValue}"
ContentStringFormat="Visits {0:###,###,###}"/>
</StackPanel>
</ToolTipService.ToolTip>
<Ellipse StrokeThickness="{TemplateBinding BorderThickness}"
Stroke="{TemplateBinding BorderBrush}"
Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Real Time Graph" VerticalAlignment="Top" Grid.Row="0" />
<chartingToolkit:Chart Grid.Row="1"
Name="RTGraph"
BorderThickness="0" >
</chartingToolkit:Chart>
</Grid>
</Grid>
</DockPanel>
</Window>
As SeeSharp says, Snoop allows you to view the object tree at runtime (and change values and see results etc). However, I think your problem here might be that you're not explicitly applying the style on the <chartingToolkit:Chart /> object.
Try one of the following to see if it makes a difference:
Apply style on object:
<chartingToolkit:Chart
...
Style="{DynamicResource GoogleLineDataPointStyle}"
...
>
Or remove the key from the style so that it only has a TargetType attribute (should make it the default style for all objects of that type:
<Style TargetType="chartingToolkit:LineDataPoint">
...
</Style>
Since you've given the styles an x:Key. you need to explicitly set the style property of your items to use that style as a resource.
Have you tried removing the x:Key properties from your style, and moving your style declaration from the grid and into the chart?
See output window in VS. All binding errors logged in this window. Also, tool Snoop alow to see bindings with errors.
If this is a WPF application, i would like to suggest one silly thing. Excuse me for that. Please copy and paste the same code into a silverlight application and then inspect the element using Firebug.
Also, in your code snippet, i think you need to give :
TargetType="{x:Type Polyline}"
TargetType="{x:Type chartingToolkit:LineDataPoint}"
If you want these styles to be applied on the target type automatically, then remove the x:Key.
Also, you can find a list of useful WPF utilities # http://www.simple-talk.com/dotnet/.net-tools/essential-tools-for-the-wpf-novice/

Categories

Resources