Wpf Rounded corners progress bar - c#

I'm trying to make a simple progress bar with rounded corners.
This is my xaml:
<Grid>
<ProgressBar Minimum="0" Maximum="100" Height="50" Value="50" Name="pbStatus" BorderBrush="Black" BorderThickness="3" Foreground="#336699" />
<TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
I'm trying to look for the Border-Radius property.... but i just find it.
Any help please?
Thanks.

From Visual Studio Designer Right Click on the ProgressBar > Edit Template > Edit a Copy,
In the Generated Style add CornerRadius to the Border and set the RadiusX and RadiusY in the filling Rectangles :
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="30"/>
<Rectangle x:Name="PART_Track" />
<Grid x:Name="PART_Indicator" ClipToBounds="true" HorizontalAlignment="Left">
<Rectangle x:Name="Indicator" Fill="{TemplateBinding Foreground}" RadiusX="30" RadiusY="30"/>
<Rectangle x:Name="Animation" Fill="{TemplateBinding Foreground}" RenderTransformOrigin="0.5,0.5" RadiusX="30" RadiusY="30">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>

Put a border inside and set the corner radius property of the border instead. Here is the link describing this
progressbar bar style right radius

Related

Rotating image inside a border

Hi,
I have a image inside a Border which I would provide an angle for. Currently I am just hard coding it to 45.
My problem is that the image is displayed at the left of the border. I want it to be in the centre and fit inside the border.
When I provide an angle I want it to rotate inside the border.
<Grid Background="gray" HorizontalAlignment="Right" Width="36" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Line Grid.Column="0" X1="0" X2="0" Y1="0" Y2="500" Fill="Black" Stroke="Black" StrokeThickness="7" StrokeDashArray="0.5 0.5"
/>
<Border Grid.Column="1" Background="DarkGreen" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Image Source="pack://application:,,,/WpfApplication3;component/Resources/MyImage.png">
<Image.RenderTransform >
<RotateTransform Angle="45" />
</Image.RenderTransform>
</Image >
</Border>
<Line Grid.Column="2" X1="0" X2="0" Y1="0" Y2="5000" Fill="Black" Stroke="Black" StrokeThickness="7" StrokeDashArray="0.5 0.5"
/>
</Grid>
Please help
Set the RenderTransformOrigin property to the center of the image. RenderTransformOrigin uses relative coordinates, hence the center is at 0.5,0.5:
<Border ClipToBounds="True">
<Image ... RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform Angle="45"/>
</Image.RenderTransform>
</Image>
</Border>
In order to fit the rotated Image in the Border control, you could set its LayoutTransform:
<Border>
<Image ...>
<Image.LayoutTransform>
<RotateTransform Angle="45"/>
</Image.LayoutTransform>
</Image>
</Border>
You can use CenterX and CenterY properties of RotateTransform to set the center of rotation.
If you need the image to expand the border size when rotating you need to use LayoutTransform.
For instance it could be done as:
<Border>
<Image Source="pack://application:,,,/WpfApplication3;component/Resources/MyImage.png" x:Name="image">
<Image.RenderTransform >
<RotateTransform
Angle="45"
CenterX="{Binding ElementName=image, Path=ActualWidth, Converter={StaticResource ResourceKey=DivideBy2Converter}}"
CenterY="{Binding ElementName=image, Path=ActualHeight, Converter={StaticResource ResourceKey=DivideBy2Converter}}"
/>
</Image.RenderTransform>
</Image >
</Border>
Edit:
Take ActualSize of image, not border
I wanted to make an image similar to a clock arm. Given the angle it would just display it. The problem was that the image was not stretching at 120 or 160 and the arm would become shorter.
I finally achieved by making a rectangle and calculating its margins and CenterY
<Rectangle
Stroke="yellow" Fill="Yellow">
<Rectangle.Margin>
<MultiBinding Converter="{StaticResource MarginConverter}">
<MultiBinding.Bindings>
<Binding ElementName="border" Path="ActualWidth"/>
<Binding ElementName="border" Path="ActualHeight"/>
</MultiBinding.Bindings>
</MultiBinding>
</Rectangle.Margin>
<Rectangle.RenderTransform>
<RotateTransform CenterX="0"
CenterY="{Binding ElementName=border, Path=ActualHeight, Converter={StaticResource CalculateRectCenterY}}" Angle="120" />
</Rectangle.RenderTransform>
</Rectangle>
Michał Żochowski's post gave me the idea although his answer did not solve me problem exactly

How to use image in WPF progressbar?

I have a picture, I want to use it in WPF as a progressbar.
Please look at the image to understand this.
The code below, repeated the image.
The moving progress-box above the progressbar.
I have tried this
<ControlTemplate
x:Key="ImageProgressBarTemplate"
TargetType="ProgressBar">
<ControlTemplate.Triggers>
<EventTrigger
RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard
x:Name="str">
<RectAnimation
x:Name="quatanim"
Storyboard.TargetName="imgbrush"
Storyboard.TargetProperty="(ImageBrush.Viewport)"
From="0,0,36,36"
To="36,0,36,36"
Duration="0:0:5"
AutoReverse="False"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
<!-- Custom progress bar goes here -->
<Border
Name="PART_Track"
Width="{TemplateBinding Width}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Height="{TemplateBinding Height}"
CornerRadius="0"
Padding="1.5">
<Grid>
<!-- Rounded mask (stretches to fill Grid) -->
<Border
Name="mask"
Background="#EEEEEE"
CornerRadius="0" />
<!-- Any content -->
<Rectangle
Name="PART_Indicator"
HorizontalAlignment="Left"
Height="{TemplateBinding Height}">
<Rectangle.OpacityMask>
<VisualBrush
Visual="{Binding ElementName=mask}" />
</Rectangle.OpacityMask>
<Rectangle.Fill>
<ImageBrush
x:Name="imgbrush"
ImageSource="/myproject;component/Assets/myimage.png"
AlignmentX="Left"
Stretch="Fill"
TileMode="Tile"
AlignmentY="Top"
ViewportUnits="Absolute"
Viewport="0,0,36,36"
ViewboxUnits="RelativeToBoundingBox"
Viewbox="0,0,1,1">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
<ProgressBar Template="{StaticResource ImageProgressBarTemplate}"/>
The all that I need is a detailed tutorial of how to use image in wpf progressbar for this kind of images.
You have to design your own template of progressbar.
<ControlTemplate TargetType="ProgressBar">
<Canvas>
<ProgressBar x:Name="pgbar" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
Value="{TemplateBinding Value}"
Minimum="{TemplateBinding Minimum}"
Maximum="{TemplateBinding Maximum}"/>
<Image Source="image.PNG" Canvas.Left="{TemplateBinding Value}">
<Image.RenderTransform>
<!-- width / 2 and height /2-->
<TranslateTransform X="-56" Y="-25"/>
</Image.RenderTransform>
</Image>
</Canvas>
</ControlTemplate>
An improvement for the answer of Klaus Fischer:
Here is the ProgressBar:
<ProgressBar Value="{Binding ProgressbarValue}" Template="{StaticResource Progressbar2}" />
And here is the template (See post of Klaus Fischer):
<ControlTemplate x:Key="Progressbar2" TargetType="ProgressBar">
<Canvas >
<ProgressBar x:Name="pgbar" Visibility="Hidden" Width="{Binding ElementName=StatusGrid,Path=ActualWidth}" Background="Transparent" Value="{TemplateBinding Value}" />
<Image Source="Resources/Images/running.png" Height="42px" Canvas.Left="{TemplateBinding Value, Converter={StaticResource WidthConverter}, ConverterParameter={x:Reference pgbar}}" />
</Canvas>
</ControlTemplate>
As you can see, there is a converter in the
Canvas.Left
property.
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var bar = ((System.Windows.Controls.ProgressBar) parameter);
var percentPixe = bar.ActualWidth/100;
return percentPixe*(double) value-42;
}
The expression
value-42
handles the size of the image, otherwise the image would be in front of the real ProgressBar.
This should do the job.

How to implement custom progressbar in XAML

I'm trying to implement custom "progressbar" which is based on image that is not rectangle. I through I could use opacitymask to achieve this, but I haven't yet figured out how to do it. I have an image which has transparent background and it's colored on white from inside. Initial state is that image is completely blue, and end state is that image is completely white (except borders will remain black)
Currently I have this kind of XAML code for this, but I dont see any blue filling over image...
<Style TargetType="ProgressBar" x:Name="ImageProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="{TemplateBinding Margin}"
Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Grid>
<Image Source="Assets/emptyprogress.png" Stretch="Fill" />
<Rectangle Fill="Blue">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="Assets/emptyprogress.png" Stretch="Fill" />
</Rectangle.OpacityMask>
<Rectangle.Clip>
<RectangleGeometry x:Name="CLIPRECTANGLE" />
</Rectangle.Clip>
</Rectangle>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ProgressBar Grid.Row="3" Style="{StaticResource ImageProgressBar}"
Width="200"
Height="200"
Minimum="0"
Maximum="100"
Value="50" />
This is what I have and this should be end point
This is what I want
Your fill rectangle needs to be named ProgressBarIndicator for the ProgressBar to be able to find and fill it.
You might also consider replacing your tooth image with a PathGeometry. You can then use the same geometry to Clip the rectangle.
Here's an example with Ellipses and inappropriately hard-coded values (I'll leave a more complicated path for an artist :) )
<Grid x:Name="DeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Visible">
<Ellipse Height="50" x:Name="ProgressBarTrack" Fill="{TemplateBinding Background}" />
<Rectangle Height="50" x:Name="ProgressBarIndicator" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Left" >
<Rectangle.Clip>
<EllipseGeometry Center="200,25" RadiusY="25" RadiusX="200" />
</Rectangle.Clip>
</Rectangle>
</Grid>

WPF Rectangle with different stroke thickness on sides or Border with dashed stroke?

I know I can create a dashed border with a rectangle or a border with different stroke thickness for different sides:
<StackPanel Orientation="Horizontal">
<Rectangle Stroke="Green" StrokeThickness="2" StrokeDashArray="4 2" Fill="LightGreen" Height="64" Width="32" Margin="5"/>
<Border BorderBrush="Green" BorderThickness="2,2,2,0" Background="LightGreen" Height="64" Width="32" Margin="5" />
</StackPanel>
Is there anyway I can achieve both:
?
UPDATE: This needs to fill the space in it's parent (unlike my example with fixed sizes), e.g. a Grid - so a DrawingGeometry which has fixed sizes and my own Pen cannot be used to achieve this.. can it?
Try this:
<Border BorderThickness="4,4,4,0" Background="LightGreen">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle
Stroke="Green" Fill="LightGreen"
StrokeDashArray="4 2"
StrokeThickness="4"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"/>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
</Border>
It's border, so when put inside of grid it will use the available space and you can set different width for every side, it uses rectangle for visual brush, so you can easily set the borders to dashed.
A hacky solution but it works is to cover the side of the dashed Rectangle you want hidden:
<Grid Width="100" Height="100">
<Rectangle Stroke="Green" StrokeThickness="4" StrokeDashArray="4 2" Fill="LightGreen" Margin="10"/>
<Rectangle StrokeThickness="0" Height="4" Margin="10" VerticalAlignment="Bottom" Fill="LightGreen"/>
</Grid>

Disabling or hiding title bar

I'm using the http://wpfmdi.codeplex.com/ library to handle MDI in my WPF application.
I've got a Canvas which contains a child container, which in turn contains a number of small windows.
I would like to disable the titlebar on my child windows. Is this possible? I haven't found a single property which achieves this, especially since the MdiChild object is of type Control rather than Window.
This is my code for creating an MDIChild, which contains an object of my TableWindow class.
MdiChild child = new MdiChild()
{
MaximizeBox = false,
MinimizeBox = false,
Resizable = true,
ShowIcon = false,
Content = tableWindow.Content as UIElement
};
mainContainer.Children.Add(child);
EDIT:
Since its a Control so you have to override its default template (ControlTemplate).
In source code you will see two xamls - Aero.xaml and Luna.xaml containing the style for MdiChild control. Source code can be seen here. Just get rid of StackPanel(ButtonsPanel) containing buttons and Grid(HeaderContent).
Thats the power WPF gives us, you can customize any control to give it a look whatever you feel like by overriding its ControlTemplate.
EDIT
To override the template you have to redefine it in your xaml. What you have to do is create a style again in your Window resources, set the template for the control and it will automatically override the default control template. Simply copy paste the entire template from here and remove the StackPanel and Grid which i mentioned above.
<Window.Resources>
<Style TargetType="{x:Type mdi:MdiChild}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<!-- Copy paste entire template here and
just remove the StackPanel and Grid -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
EDIT2
Replace your ControlTemplate with this to disable the title bar but still enable the drag operation and resizable operation for your control -
<ControlTemplate TargetType="{x:Type mdi:MdiChild}">
<Border Name="BaseBorder" BorderThickness="1" CornerRadius="5,5,0,0"
Background="{StaticResource BackBorderBackgroundBrush}"
BorderBrush="{StaticResource BackBorderBrush}">
<Grid>
<Border Name="ContentBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentControl Content="{TemplateBinding Content}" />
</Border>
<Thumb Name="DragThumb" Height="20" Margin="0,0,40,0"
VerticalAlignment="Top" Opacity="0"/>
<Rectangle Name="LeftBorder" Width="1" HorizontalAlignment="Left"
RadiusX="9" RadiusY="9"
Fill="{StaticResource NearBorderBrush}" />
<Rectangle Name="TopBorder" Height="1" VerticalAlignment="Top"
RadiusX="9" RadiusY="9"
Fill="{StaticResource NearBorderBrush}" />
<Rectangle Name="RightBorder" Width="1" HorizontalAlignment="Right"
RadiusX="9" RadiusY="9"
Fill="{StaticResource FarBorderBrush}" />
<Rectangle Name="BottomBorder" Height="1" VerticalAlignment="Bottom"
RadiusX="9" RadiusY="9"
Fill="{StaticResource FarBorderBrush}" />
<Thumb Name="ResizeLeft" Width="6" HorizontalAlignment="Left"
Margin="0,6,0,6" Opacity="0" Cursor="SizeWE"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeTop" Height="4" VerticalAlignment="Top"
Margin="6,0,6,0" Opacity="0" Cursor="SizeNS"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeRight" Width="6" HorizontalAlignment="Right"
Margin="0,6,0,6" Opacity="0" Cursor="SizeWE"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeBottom" Height="6" VerticalAlignment="Bottom"
Margin="6,0,6,0" Opacity="0" Cursor="SizeNS"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeTopLeft" Width="6" Height="6"
HorizontalAlignment="Left" VerticalAlignment="Top" Opacity="0"
Cursor="SizeNWSE"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeTopRight" Width="6" Height="6"
HorizontalAlignment="Right" VerticalAlignment="Top"
Opacity="0" Cursor="SizeNESW"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeBottomRight" Width="6" Height="6"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Opacity="0" Cursor="SizeNWSE"
IsHitTestVisible="{TemplateBinding Resizable}" />
<Thumb Name="ResizeBottomLeft" Width="6" Height="6"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Opacity="0" Cursor="SizeNESW"
IsHitTestVisible="{TemplateBinding Resizable}" />
</Grid>
</Border>
</ControlTemplate>

Categories