Ho bisogno di aiuto per l'attuazione di una barra di avanzamento circolare in questo modo:Come creare una circolare stile ProgressBar
Come devo realizzare il Circolo di colmare aumentando Value
proprietà?
Ho bisogno di aiuto per l'attuazione di una barra di avanzamento circolare in questo modo:Come creare una circolare stile ProgressBar
Come devo realizzare il Circolo di colmare aumentando Value
proprietà?
Avete un paio di opzioni: la prima è di creare il modello del controllo ProgressBar
. Questo risulta essere un po 'complicato. Ho scritto un post sul blog che descrive come use an attached ViewModel to achieve the required effect.
L'altra alternativa è creare il proprio controllo da zero. Si potrebbe fare la seguente:
E perché non creare il modello ProgressBar esistente? I CustomControls in WPF sono esattamente per questo scopo. Qual è il punto di aver attraversato tutte le seccature di creare un controllo senza look quando non hai intenzione di riutilizzarlo quando tutto ciò di cui hai bisogno è una diversa rappresentazione di esso nell'interfaccia utente? – NVM
@ NVM, sono d'accordo con te in linea di massima, ma probabilmente ci sarà bisogno di un codice qui. Non esiste un modo semplice per creare un arco di ritaglio utilizzando le forme incorporate in WPF utilizzando XAML puro. Se si utilizza Expression Blend SDK, c'è una forma ad arco che può farlo abbastanza facilmente. Quindi l'OP avrà probabilmente bisogno di creare un qualche tipo di controllo che possa disegnare la torta. Ma l'implementazione della barra di avanzamento dovrebbe essere un modello che utilizza questo nuovo controllo "a torta". – Josh
Vedere la mia risposta modificata. Non è che non puoi farlo nel modo che suggerisci. Penso che in generale sia meglio scrivere meno codice possibile. – NVM
Hai guardato ValueConverter
s? È possibile associare alla proprietà Value nel modello utilizzando TemplateBinding
e utilizzare un convertitore di valori appropriato per modificare il valore in quello che è utile per una barra di avanzamento circolare.
EDIT:
Nel modello:
Aggiungi un cerchio riempire con il colore giallo.
Aggiungere un altro cerchio in cima con il colore arancione.
utilizzare un convertitore valore (o convertitore di valori più) per restituire un (segmento di arco utilizzando possibilmente) la geometria di ritaglio per il cerchio aggiunto 2.
clip del cerchio 2. con la geometria restituito in 3.
Downvoter mi restituisce il mio repz.
-1, Questo non può essere raggiunto con un convertitore di valori. Deve essere affrontato nell'albero visivo. – Josh
Vedere le nuove modifiche. – NVM
Ho rimosso il downvote perché sì, immagino che tecnicamente potresti farlo in quel modo. :) Ma sarebbe molto più semplice farlo con una sottoclasse di UIElement, quindi inserirla nel modello di una ProgressBar. – Josh
È un po 'complicato ma non impossibile. Ecco la mia implementazione utilizzando animazioni fluide da guidare. I convertitori di valori dovrebbero essere utilizzati per creare un CircularProgressBar.
CircularProgressBar.cs
public partial class CircularProgressBar : ProgressBar
{
public CircularProgressBar()
{
this.ValueChanged += CircularProgressBar_ValueChanged;
}
void CircularProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
CircularProgressBar bar = sender as CircularProgressBar;
double currentAngle = bar.Angle;
double targetAngle = e.NewValue/bar.Maximum * 359.999;
DoubleAnimation anim = new DoubleAnimation(currentAngle, targetAngle, TimeSpan.FromMilliseconds(500));
bar.BeginAnimation(CircularProgressBar.AngleProperty, anim, HandoffBehavior.SnapshotAndReplace);
}
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
// Using a DependencyProperty as the backing store for Angle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(CircularProgressBar), new PropertyMetadata(0.0));
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
// Using a DependencyProperty as the backing store for StrokeThickness. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StrokeThicknessProperty =
DependencyProperty.Register("StrokeThickness", typeof(double), typeof(CircularProgressBar), new PropertyMetadata(10.0));
}
AngleToPointConverter.cs
class AngleToPointConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double angle = (double)value;
double radius = 50;
double piang = angle * Math.PI/180;
double px = Math.Sin(piang) * radius + radius;
double py = -Math.Cos(piang) * radius + radius;
return new Point(px, py);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
AngleToIsLargeConverter.cs
class AngleToIsLargeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double angle = (double)value;
return angle > 180;
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
xmlns:my="clr-namespace:WpfApplication1">
<Application.Resources>
<my:AngleToPointConverter x:Key="prConverter"/>
<my:AngleToIsLargeConverter x:Key="isLargeConverter"/>
<Style x:Key="circularProgressBar" TargetType="my:CircularProgressBar">
<Setter Property="Value" Value="10"/>
<Setter Property="Maximum" Value="100"/>
<Setter Property="StrokeThickness" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="my:CircularProgressBar">
<Canvas Width="100" Height="100">
<Ellipse Width="100" Height="100" Stroke="LightGray"
StrokeThickness="1"/>
<Path Stroke="{TemplateBinding Background}"
StrokeThickness="{TemplateBinding StrokeThickness}">
<Path.Data>
<PathGeometry>
<PathFigure x:Name="fig" StartPoint="50,0">
<ArcSegment RotationAngle="0" SweepDirection="Clockwise"
Size="50,50"
Point="{Binding Path=Angle, Converter={StaticResource prConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
IsLargeArc="{Binding Path=Angle, Converter={StaticResource isLargeConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
>
</ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Border Width="100" Height="100">
<TextBlock Foreground="Gray" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Path=Value, StringFormat={}%{0},
RelativeSource={RelativeSource TemplatedParent}}"
FontSize="{TemplateBinding FontSize}"/>
</Border>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Può essere più personalizzato aggiungendo alcune proprietà come InnerRadius, Raggio ecc
So è un vecchio problema, ma comunque ecco la mia soluzione:
PER WinForms:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public class CircularProgressBar : Control
{
/* CREDITS:
* Autor: Sajjad Arif Gul/October 12, 2016/C#, Source Codes
* https://www.csharpens.com/c-sharp/circular-progress-bar-in-c-sharp-windows-form-applications-23/
* Modified by Jhollman Chacon, 2017 */
#region Enums
public enum _ProgressShape
{
Round,
Flat
}
#endregion
#region Variables
private long _Value;
private long _Maximum = 100;
private Color _ProgressColor1 = Color.Orange;
private Color _ProgressColor2 = Color.Orange;
private Color _LineColor = Color.Silver;
private _ProgressShape ProgressShapeVal;
#endregion
#region Custom Properties
public long Value
{
get { return _Value; }
set
{
if (value > _Maximum)
value = _Maximum;
_Value = value;
Invalidate();
}
}
public long Maximum
{
get { return _Maximum; }
set
{
if (value < 1)
value = 1;
_Maximum = value;
Invalidate();
}
}
public Color ProgressColor1
{
get { return _ProgressColor1; }
set
{
_ProgressColor1 = value;
Invalidate();
}
}
public Color ProgressColor2
{
get { return _ProgressColor2; }
set
{
_ProgressColor2 = value;
Invalidate();
}
}
public Color LineColor
{
get { return _LineColor; }
set
{
_LineColor = value;
Invalidate();
}
}
public _ProgressShape ProgressShape
{
get { return ProgressShapeVal; }
set
{
ProgressShapeVal = value;
Invalidate();
}
}
#endregion
#region EventArgs
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
SetStandardSize();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
SetStandardSize();
}
protected override void OnPaintBackground(PaintEventArgs p)
{
base.OnPaintBackground(p);
}
#endregion
#region Methods
public CircularProgressBar()
{
Size = new Size(130, 130);
Font = new Font("Segoe UI", 15);
MinimumSize = new Size(100, 100);
DoubleBuffered = true;
Value = 57;
ProgressShape = _ProgressShape.Flat;
this.ForeColor = Color.DimGray;
}
private void SetStandardSize()
{
int _Size = Math.Max(Width, Height);
Size = new Size(_Size, _Size);
}
public void Increment(int Val)
{
this._Value += Val;
Invalidate();
}
public void Decrement(int Val)
{
this._Value -= Val;
Invalidate();
}
#endregion
#region Events
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Bitmap bitmap = new Bitmap(this.Width, this.Height))
{
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.Clear(this.BackColor);
// Dibuja la Linea
using (Pen pen2 = new Pen(LineColor))
{
graphics.DrawEllipse(pen2, 0x18 - 6, 0x18 - 6, (this.Width - 0x30) + 12, (this.Height - 0x30) + 12);
}
//Dibuja la Barra de Progreso
using (LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle, this._ProgressColor1, this._ProgressColor2, LinearGradientMode.ForwardDiagonal))
{
using (Pen pen = new Pen(brush, 14f))
{
switch (this.ProgressShapeVal)
{
case _ProgressShape.Round:
pen.StartCap = LineCap.Round;
pen.EndCap = LineCap.Round;
break;
case _ProgressShape.Flat:
pen.StartCap = LineCap.Flat;
pen.EndCap = LineCap.Flat;
break;
}
//Aqui se dibuja el Progreso
graphics.DrawArc(pen, 0x12, 0x12, (this.Width - 0x23) - 2, (this.Height - 0x23) - 2, -90, (int)Math.Round((double)((360.0/((double)this._Maximum)) * this._Value)));
}
}
//Dibuja el Texto de Progreso:
Brush FontColor = new SolidBrush(this.ForeColor);
SizeF MS = graphics.MeasureString(Convert.ToString(Convert.ToInt32((100/_Maximum) * _Value)), Font);
graphics.DrawString(Convert.ToString(Convert.ToInt32((100/_Maximum) * _Value)), Font, FontColor, Convert.ToInt32(Width/2 - MS.Width/2), Convert.ToInt32(Height/2 - MS.Height/2));
e.Graphics.DrawImage(bitmap, 0, 0);
graphics.Dispose();
bitmap.Dispose();
}
}
}
#endregion
}
ATTUAZIONE:
di controllo appare come questa
godere.
il collegamento in questione è rotto. Si prega di inserire un'immagine nella domanda. –