What appeared to be straight forward proved to be a bit more difficult than I anticipated. I wanted to create a customized ProgressBar for the Windows Phone. The ProgressBar should take any image as input and Fill the image depending on the progress indicated by the Value property.
So I create a class deriving from ProgressBar:
using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace CustomControls { [TemplatePart(Name="CLIPRECTANGLE", Type=typeof(RectangleGeometry))] public class ImageProgressBar : ProgressBar { public ImageProgressBar() { this.DefaultStyleKey = typeof(ImageProgressBar); } public ImageSource Source { get { return (ImageSource)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageProgressBar), new PropertyMetadata(null)); public Brush Fill { get { return (Brush)GetValue(FillProperty); } set { SetValue(FillProperty, value); } } public static readonly DependencyProperty FillProperty = DependencyProperty.Register("Fill", typeof(Brush), typeof(ImageProgressBar), new PropertyMetadata(null)); private RectangleGeometry _clip; public override void OnApplyTemplate() { base.OnApplyTemplate(); _clip = this.GetTemplateChild("CLIPRECTANGLE") as RectangleGeometry; this.ValueChanged += ImageProgressBar_ValueChanged; this.SizeChanged += ImageProgressBar_SizeChanged; } void ImageProgressBar_SizeChanged(object sender, SizeChangedEventArgs e) { UpdateClip(); } void ImageProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { UpdateClip(); } private void UpdateClip() { if (_clip != null) { _clip.Rect = new Rect(0, 0, this.ActualWidth, this.ActualHeight * ((this.Value - this.Minimum) / (this.Maximum - this.Minimum))); } } } }
The Source property can be used to point to the image. The Fill property points to a brush that should fill the image. The _clip points to a RectangleGeometry in the template that has to cut off a part of the fill according to the progress.
The UpdateClip adjusts the Rectangle based on the size of the progress bar and the progress indicated by the Value property.
Next up; the template:
<ResourceDictionary class="wlWriterEditableSmartContent"><pre> [sourcecode language="xml" htmlscript="false"] <my:ImageProgressBar Width=&quot;100&quot; Height=&quot;100&quot; Fill=&quot;Red&quot; Source=&quot;ProgressBar.png&quot; Minimum=&quot;100&quot; Maximum=&quot;200&quot; Value=&quot;{Binding ElementName=slider1, Path=Value, Mode=TwoWay}&quot; /> <Slider Margin=&quot;0&quot; Name=&quot;slider1&quot; VerticalAlignment=&quot;Top&quot; Minimum=&quot;100&quot; Maximum=&quot;200&quot; Value=&quot;125&quot; />
I added a slider to see the progress on the Phone.
19 comments
Seems like sample not working.
Nishant
Could you elaborate? It is working on my machine.
Erno de Weerd
[…] be just that…. great post on PivotViewer and great end to the series, plagiarized quote and all :)Windows Phone 7 Custom ProgressBarErno de Weerd has a very cool post up about doing a custom progress bar for WP7 using any image… […]
WindowsDevNews.com
I tested the download on a different machine and found out what was wrong. I updated the download. Use that or simply add an existing project to the solution in Visual Studio and add the project that is not referenced.
Erno de Weerd
Yeah !! its working now. Thanks !!
Nice article
Nishant
No problem. Enjoy!
Erno de Weerd
My own implementation http://www.calabonga.com/Blog/ViewPost.aspx?id=72
Calabonga
Looks fine (though my Russian isn’t good enough to judge any other thing than the C#, XAML and screenshots 🙂 ) I tried to avoid using animation because that will use CPU power.
Erno de Weerd
ProgressBarDemo-v2 folder contain two folder and i tried to open ProgressBar first and it gives error like this “Error 1 The referenced assembly “C:UsersDesktopProgressbarProgressBarDemo-v2ProgressBarBinDebugProgressBar.dll” was not found. If this assembly is produced by another one of your projects, please make sure to build that project before building this one. DemoApp
”
what to do?
john
Open the sln file in the root. The solution loads both projects. and takes care of the building order and dependencies.
Erno de Weerd
Need your help urgent :i just want to use your custom progress bar but i want to fill the bar horizontally instead of vertical can you please help me what should i change in your code to get the desired result?
waiting for your reply
thanks is advance.
john
Just change the UpdateClip() method in the ImageProgressBar control like this:
private void UpdateClip()
{
if (_clip != null)
{
_clip.Rect =
new Rect(0, 0,
this.ActualWidth * ((this.Value – this.Minimum) / (this.Maximum – this.Minimum)),
this.ActualHeight );
}
}
Erno de Weerd
it’s done and i noticed that when i tried to change the position of image it gets invisible ? how can i place that image according to my position?
john
There is an error in the generic.xaml Remove the Margin from the Border
Erno de Weerd
I downloaded the example. But i can’t debug it by Visual Studio . I only deploy it.
Daniel
What do you mean that you can’t debug it? Do you just want to use it without building it?
Erno de Weerd
I could build project , deploy project, but I can’t debug . The “Start Debugging (F5)” is gray
Daniel
Did you set the test client as a start up project?
Erno de Weerd
You are right!! Thank you very much. I can debug now.
Daniel