Skip to content

Commit e99c638

Browse files
committed
circular progress..coming along nicely!
1 parent e54673c commit e99c638

File tree

5 files changed

+314
-4
lines changed

5 files changed

+314
-4
lines changed

MainDemo.Wpf/App.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Application x:Class="MaterialDesignColors.WpfExample.App"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4-
StartupUri="MainWindow.xaml">
4+
StartupUri="ProvingGround.xaml">
55
<Application.Resources>
66
<ResourceDictionary>
77
<ResourceDictionary.MergedDictionaries>

MainDemo.Wpf/MainDemo.Wpf.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
<Compile Include="ProvingGround.xaml.cs">
107107
<DependentUpon>ProvingGround.xaml</DependentUpon>
108108
</Compile>
109+
<Compile Include="ProvingGroundStuff\Converters.cs" />
109110
<Compile Include="TextFields.xaml.cs">
110111
<DependentUpon>TextFields.xaml</DependentUpon>
111112
</Compile>

MainDemo.Wpf/ProvingGround.xaml

Lines changed: 172 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
xmlns:system="clr-namespace:System;assembly=mscorlib"
77
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
88
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
9+
xmlns:cicularProgressBar="clr-namespace:MaterialDesignColors.WpfExample.ProvingGroundStuff.MaterialDesignColors.WpfExample.ProvingGroundStuff.CicularProgressBar"
910
x:Class="MaterialDesignColors.WpfExample.ProvingGround"
1011
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
1112
Background="{DynamicResource MaterialDesignPaper}"
1213
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
1314
mc:Ignorable="d"
14-
d:DesignWidth="680" d:DesignHeight="120">
15+
d:DesignWidth="200" d:DesignHeight="120">
1516
<UserControl.Resources>
1617
<ResourceDictionary>
1718
<ResourceDictionary.MergedDictionaries>
@@ -25,7 +26,7 @@
2526
<ResourceDictionary>
2627
<!-- include your primary palette -->
2728
<ResourceDictionary.MergedDictionaries>
28-
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Green.xaml" />
29+
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Indigo.xaml" />
2930
</ResourceDictionary.MergedDictionaries>
3031
<!--
3132
include three hues from the primary palette (and the associated forecolours).
@@ -52,12 +53,180 @@
5253
</ResourceDictionary>
5354
</ResourceDictionary.MergedDictionaries>
5455

56+
<cicularProgressBar:StartPointConverter x:Key="StartPointConverter" />
57+
<cicularProgressBar:ArcSizeConverter x:Key="ArcSizeConverter" />
58+
<cicularProgressBar:ArcEndPointConverter x:Key="ArcEndPointConverter" />
59+
<cicularProgressBar:LargeArcConverter x:Key="LargeArcConverter" />
60+
<cicularProgressBar:RotateTransformConverter x:Key="RotateTransformConverter" />
61+
<cicularProgressBar:RotateTransformCentreConverter x:Key="RotateTransformCentreConverter" />
62+
63+
<Style x:Key="MaterialDesignCicularProgressBar" TargetType="{x:Type ProgressBar}">
64+
<Setter Property="Foreground" Value="{DynamicResource PrimaryHueMidBrush}" />
65+
<Setter Property="Background" Value="Transparent" />
66+
<Setter Property="Width" Value="20" />
67+
<Setter Property="Height" Value="20" />
68+
<Setter Property="Template">
69+
<Setter.Value>
70+
<ControlTemplate TargetType="{x:Type ProgressBar}">
71+
<ControlTemplate.Resources>
72+
<Storyboard x:Key="IsIndeterminateStoryboard" TargetName="RotateTransform" TargetProperty="Angle" RepeatBehavior="Forever">
73+
<DoubleAnimation From="0" To="359" Duration="0:0:2" />
74+
</Storyboard>
75+
</ControlTemplate.Resources>
76+
<Grid x:Name="TemplateRoot" Background="{TemplateBinding Background}" ClipToBounds="False">
77+
<Grid x:Name="PathGrid" Margin="2" />
78+
<Canvas>
79+
<Path x:Name="Path" Stroke="{TemplateBinding Foreground}" StrokeThickness="3"
80+
Canvas.Top="2" Canvas.Left="2"
81+
RenderTransformOrigin="0, 0">
82+
<Path.Data>
83+
<PathGeometry>
84+
<PathFigure StartPoint="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource StartPointConverter}, Mode=OneWay}">
85+
<ArcSegment Size="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource ArcSizeConverter}, Mode=OneWay}"
86+
SweepDirection="Clockwise"
87+
>
88+
<ArcSegment.IsLargeArc>
89+
<MultiBinding Converter="{StaticResource LargeArcConverter}">
90+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
91+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
92+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
93+
</MultiBinding>
94+
</ArcSegment.IsLargeArc>
95+
<ArcSegment.Point>
96+
<MultiBinding Converter="{StaticResource ArcEndPointConverter}">
97+
<Binding ElementName="PathGrid" Path="ActualWidth" />
98+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
99+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
100+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
101+
</MultiBinding>
102+
</ArcSegment.Point>
103+
</ArcSegment>
104+
</PathFigure>
105+
</PathGeometry>
106+
</Path.Data>
107+
<Path.RenderTransform>
108+
<TransformGroup>
109+
<RotateTransform x:Name="RotateTransform"
110+
CenterX="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource RotateTransformCentreConverter}, Mode=OneWay}"
111+
CenterY="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource RotateTransformCentreConverter}, Mode=OneWay}">
112+
<RotateTransform.Angle>
113+
<MultiBinding Converter="{StaticResource RotateTransformConverter}">
114+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
115+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
116+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
117+
</MultiBinding>
118+
</RotateTransform.Angle>
119+
</RotateTransform>
120+
</TransformGroup>
121+
</Path.RenderTransform>
122+
</Path>
123+
</Canvas>
124+
</Grid>
125+
<ControlTemplate.Triggers>
126+
<Trigger Property="IsIndeterminate" Value="True">
127+
<Trigger.EnterActions>
128+
<BeginStoryboard Storyboard="{StaticResource IsIndeterminateStoryboard}"
129+
Name="IsIndeterminateStoryboard"/>
130+
</Trigger.EnterActions>
131+
<Trigger.ExitActions>
132+
<RemoveStoryboard BeginStoryboardName="IsIndeterminateStoryboard" />
133+
</Trigger.ExitActions>
134+
</Trigger>
135+
<!--
136+
<MultiTrigger>
137+
<MultiTrigger.Conditions>
138+
<Condition Property="IsIndeterminate" Value="True" />
139+
<Condition Property="Value" Value="0" />
140+
</MultiTrigger.Conditions>
141+
<MultiTrigger.EnterActions>
142+
<BeginStoryboard Storyboard="{StaticResource IsFullyIndeterminateStoryboard}"
143+
Name="IsFullyIndeterminateStoryboard"/>
144+
</MultiTrigger.EnterActions>
145+
<MultiTrigger.ExitActions>
146+
<RemoveStoryboard BeginStoryboardName="IsFullyIndeterminateStoryboard" />
147+
</MultiTrigger.ExitActions>
148+
</MultiTrigger>
149+
-->
150+
</ControlTemplate.Triggers>
151+
</ControlTemplate>
152+
</Setter.Value>
153+
</Setter>
154+
</Style>
155+
55156
</ResourceDictionary>
56157

158+
159+
57160
</UserControl.Resources>
58161

59-
<Grid>
162+
<Grid VerticalAlignment="Top">
163+
<Grid.RowDefinitions>
164+
<RowDefinition Height="Auto" />
165+
<RowDefinition Height="Auto" />
166+
<RowDefinition />
167+
<RowDefinition />
168+
</Grid.RowDefinitions>
169+
<Grid.ColumnDefinitions>
170+
<ColumnDefinition Width="Auto" />
171+
<ColumnDefinition Width="*" />
172+
</Grid.ColumnDefinitions>
173+
174+
<ProgressBar Style="{StaticResource MaterialDesignCicularProgressBar}"
175+
x:Name="DeterminateCircularProgress"
176+
VerticalAlignment="Center" Margin="12 12 0 12" />
177+
<TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Margin="12" TextWrapping="Wrap">Standard deterministic progress bar, running from 0 to 100%. &#160;For the purpose of the demo, a storyboard is used to animate the .Value property.</TextBlock>
178+
179+
<ProgressBar Style="{StaticResource MaterialDesignCicularProgressBar}"
180+
Value="35"
181+
IsIndeterminate="True"
182+
Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="12 12 0 12"/>
183+
<TextBlock Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Margin="12" TextWrapping="Wrap">Indeterminate progress bar, at 35%.</TextBlock>
184+
185+
<ProgressBar Style="{StaticResource MaterialDesignCicularProgressBar}"
186+
Value="0"
187+
IsIndeterminate="True"
188+
Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Margin="12 12 0 12"/>
189+
<TextBlock Grid.Column="1" Grid.Row="2" VerticalAlignment="Center" Margin="12" TextWrapping="Wrap">Fully indeterminate progress bar, using .Value=0 to inform the theme.</TextBlock>
190+
191+
<ProgressBar Style="{StaticResource MaterialDesignCicularProgressBar}"
192+
Value="20"
193+
IsIndeterminate="True"
194+
x:Name="IndeterminateToDeterminateCircularProgress"
195+
Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Margin="12 12 0 12"/>
196+
<TextBlock Grid.Column="1" Grid.Row="3" VerticalAlignment="Center" Margin="12" TextWrapping="Wrap">An indeterminate job transitioning to a determinate job, completing to 100%.</TextBlock>
197+
60198

199+
200+
61201
</Grid>
202+
<UserControl.Triggers>
203+
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
204+
<EventTrigger.Actions>
205+
<BeginStoryboard>
206+
<Storyboard TargetName="DeterminateCircularProgress" TargetProperty="Value" RepeatBehavior="Forever">
207+
<DoubleAnimation From="0" To="100" Duration="0:0:2.5">
208+
<DoubleAnimation.EasingFunction>
209+
<CircleEase EasingMode="EaseOut" />
210+
</DoubleAnimation.EasingFunction>
211+
</DoubleAnimation>
212+
</Storyboard>
213+
</BeginStoryboard>
214+
<BeginStoryboard>
215+
<Storyboard TargetName="IndeterminateToDeterminateCircularProgress" RepeatBehavior="Forever" Duration="0:0:10">
216+
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsIndeterminate">
217+
<DiscreteBooleanKeyFrame Value="False" KeyTime="0:0:4" />
218+
</BooleanAnimationUsingKeyFrames>
219+
<DoubleAnimation From="20" To="100" Duration="0:0:2.5" BeginTime="0:0:4"
220+
Storyboard.TargetProperty="Value"
221+
FillBehavior="HoldEnd">
222+
<DoubleAnimation.EasingFunction>
223+
<CircleEase EasingMode="EaseOut" />
224+
</DoubleAnimation.EasingFunction>
225+
</DoubleAnimation>
226+
</Storyboard>
227+
</BeginStoryboard>
228+
</EventTrigger.Actions>
229+
</EventTrigger>
230+
</UserControl.Triggers>
62231

63232
</UserControl>
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.Windows;
8+
using System.Windows.Data;
9+
10+
namespace MaterialDesignColors.WpfExample.ProvingGroundStuff
11+
{
12+
namespace MaterialDesignColors.WpfExample.ProvingGroundStuff.CicularProgressBar
13+
{
14+
15+
public class StartPointConverter : IValueConverter
16+
{
17+
[Obsolete]
18+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
19+
{
20+
if (value is double && ((double) value > 0.0))
21+
{
22+
return new Point((double)value / 2, 0);
23+
}
24+
25+
return new Point();
26+
}
27+
28+
[Obsolete]
29+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
30+
{
31+
return Binding.DoNothing;
32+
}
33+
34+
}
35+
36+
public class ArcSizeConverter : IValueConverter
37+
{
38+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
39+
{
40+
if (value is double && ((double)value > 0.0))
41+
{
42+
return new Size((double)value / 2, (double)value / 2);
43+
}
44+
45+
return new Point();
46+
}
47+
48+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
49+
{
50+
return Binding.DoNothing;
51+
}
52+
}
53+
54+
public class ArcEndPointConverter : IMultiValueConverter
55+
{
56+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
57+
{
58+
var actualWidth = (double) values[0];
59+
var value = (double) values[1];
60+
var minimum = (double) values[2];
61+
var maximum = (double) values[3];
62+
63+
var percent = maximum <= minimum ? 1.0 : (value - minimum)/(maximum - minimum);
64+
var degrees = 360*percent;
65+
var radians = degrees*(Math.PI/180);
66+
67+
var centre = new Point(actualWidth/2, actualWidth/2);
68+
var hypotenuseRadius = (actualWidth/2);
69+
70+
var adjacent = Math.Cos(radians)*hypotenuseRadius;
71+
var opposite = Math.Sin(radians)*hypotenuseRadius;
72+
73+
return new Point(centre.X + opposite, centre.Y - adjacent);
74+
}
75+
76+
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
77+
{
78+
throw new NotImplementedException();
79+
}
80+
}
81+
82+
public class LargeArcConverter : IMultiValueConverter
83+
{
84+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
85+
{
86+
var value = (double)values[0];
87+
var minimum = (double)values[1];
88+
var maximum = (double)values[2];
89+
90+
var percent = maximum <= minimum ? 1.0 : (value - minimum) / (maximum - minimum);
91+
92+
return percent > 0.5;
93+
}
94+
95+
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
96+
{
97+
throw new NotImplementedException();
98+
}
99+
}
100+
101+
public class RotateTransformConverter : IMultiValueConverter
102+
{
103+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
104+
{
105+
var value = (double)values[0];
106+
var minimum = (double)values[1];
107+
var maximum = (double)values[2];
108+
109+
var percent = maximum <= minimum ? 1.0 : (value - minimum) / (maximum - minimum);
110+
111+
return 360*percent;
112+
}
113+
114+
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
115+
{
116+
throw new NotImplementedException();
117+
}
118+
}
119+
120+
public class RotateTransformCentreConverter : IValueConverter
121+
{
122+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
123+
{
124+
//value == actual width
125+
return (double) value/2;
126+
}
127+
128+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
129+
{
130+
return Binding.DoNothing;
131+
}
132+
}
133+
}
134+
}

MaterialDesignThemes.Wpf/PasswordFieldAssist.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,10 @@ public static PasswordBox GetManaged(DependencyObject element)
5757
return (PasswordBox)element.GetValue(ManagedProperty);
5858
}
5959
}
60+
61+
public static class ProgressBarAssist
62+
{
63+
64+
65+
}
6066
}

0 commit comments

Comments
 (0)