C# 椭圆形进度条中的垂直指示器
我正在创建一个仪表,其中我需要一个椭圆形状的进度条。我希望进度条指示器从椭圆的底部移动到顶部。我可以让它从左到右毫无问题地工作 以下是样式代码:C# 椭圆形进度条中的垂直指示器,c#,wpf,C#,Wpf,我正在创建一个仪表,其中我需要一个椭圆形状的进度条。我希望进度条指示器从椭圆的底部移动到顶部。我可以让它从左到右毫无问题地工作 以下是样式代码: <Style TargetType="ProgressBar" x:Key="HalfCircle"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Progre
<Style TargetType="ProgressBar" x:Key="HalfCircle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Grid x:Name="gridRoot">
<Ellipse x:Name="PART_Track" HorizontalAlignment="Left" Height="150" Stroke="Black" VerticalAlignment="Top" Width="150" Clip="M0.5,0.5 L153.5,0.5 L153.5,76.5 L0.5,76.5 z">
<Ellipse.Fill>
<MultiBinding>
<MultiBinding.Converter>
<converter:ProgressBarIndicatorConverter/>
</MultiBinding.Converter>
<Binding Path="Foreground" RelativeSource="{RelativeSource TemplatedParent}"/>
<!--<Binding Path="Orientation" RelativeSource="{RelativeSource TemplatedParent}"/>-->
<!--<Binding Path="Background" RelativeSource="{RelativeSource TemplatedParent}"/>-->
<!--<Binding Path="Minimum" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="Maximum" RelativeSource="{RelativeSource TemplatedParent}"/>-->
<Binding Path="IsIndeterminate" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="ActualWidth" ElementName="PART_Indicator"/>
<Binding Path="ActualHeight" ElementName="PART_Indicator"/>
<Binding Path="ActualWidth" ElementName="PART_Track"/>
<!--<Binding Path="ActualHeight" ElementName="PART_Track"/>-->
</MultiBinding>
</Ellipse.Fill>
</Ellipse>
<Decorator x:Name="PART_Indicator" RenderTransformOrigin="0.5,0.5" />
</Grid>
<!--<ControlTemplate.Triggers>
<Trigger Property="Orientation" Value="Vertical">
</Trigger>
</ControlTemplate.Triggers>-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
尝试此自定义控件:
public class FlightGauge : Control
{
private GradientStopCollection _gradStops = new GradientStopCollection();
public static DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(FlightGauge), new FrameworkPropertyMetadata(-100.0, new PropertyChangedCallback(MinValue_Changed)));
public static DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(FlightGauge), new FrameworkPropertyMetadata(100.0, new PropertyChangedCallback(MaxValue_Changed)));
public static DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(FlightGauge), new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(Value_Changed)));
public static DependencyProperty FillColorProperty = DependencyProperty.Register("FillColor", typeof(Color), typeof(FlightGauge), new FrameworkPropertyMetadata(Colors.Blue, new PropertyChangedCallback(FillColor_Changed)));
public Color FillColor
{
get { return (Color)GetValue(FillColorProperty); }
set { SetValue(FillColorProperty, value); }
}
private static void FillColor_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetFillColor();
}
private void SetFillColor()
{
//Put Instance FillColor Property Changed code here
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void Value_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetValue();
}
private void SetValue()
{
CalcTabStops();
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}
private static void MaxValue_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetMaxValue();
}
private void SetMaxValue()
{
CalcTabStops();
}
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetValue(MinValueProperty, value); }
}
private static void MinValue_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetMinValue();
}
private void SetMinValue()
{
CalcTabStops();
}
private void CalcTabStops()
{
_gradStops.Clear();
if (Value > 0)
{
double dLineValue = (1 - Value / MaxValue) /2;
if (dLineValue > 0.49) dLineValue = 0.49;
_gradStops.Add(new GradientStop(Colors.Transparent, 0.500));
_gradStops.Add(new GradientStop(Colors.Transparent, 1.0));
_gradStops.Add(new GradientStop(FillColor, 0.499));
_gradStops.Add(new GradientStop(Colors.Transparent, dLineValue));
_gradStops.Add(new GradientStop(FillColor, dLineValue +0.001));
}
else
{
double dLineValue = 0.5 + (Value / MinValue / 2);
if (dLineValue >= 1) dLineValue = 0.998;
if (dLineValue == 0.5) dLineValue = 0.5001;
_gradStops.Add(new GradientStop(Colors.Transparent, dLineValue +0.01));
_gradStops.Add(new GradientStop(Colors.Transparent, 1.0));
_gradStops.Add(new GradientStop(FillColor, dLineValue));
_gradStops.Add(new GradientStop(Colors.Transparent, 0.5));
_gradStops.Add(new GradientStop(FillColor, 0.501));
}
this.InvalidateVisual();
}
public FlightGauge()
{
BorderBrush = Brushes.Black;
}
protected override void OnRender(DrawingContext drawingContext)
{
Brush brush = null;
if (Value != 0)
{
LinearGradientBrush linBrush = new LinearGradientBrush();
linBrush.StartPoint = new Point(0.5, 0);
linBrush.EndPoint = new Point(0.5, 1);
linBrush.GradientStops = _gradStops;
brush = linBrush;
}
else
{
brush = Brushes.Transparent;
}
double dX = this.ActualWidth / 2;
double dY = this.ActualHeight / 2;
Pen pen = new Pen(BorderBrush, 2);
drawingContext.DrawEllipse(brush, pen, new Point(dX, dY), dX, dY);
drawingContext.DrawLine(pen, new Point(0, dY), new Point(this.ActualWidth, dY));
base.OnRender(drawingContext);
}
}
示例用法:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:FlightGauge x:Name="fgGauge" Width="200" Height="200" Value="{Binding ElementName=sldValue, Path=Value}" />
<Slider Name="sldValue" Minimum="-100" Maximum="100" Value="0" Grid.Row="1" />
</Grid>
一个选项。。。你可以应用一个布局变换,然后将整个东西旋转90度?等等,这个巨大的多重绑定到底在做什么?不能使用旋转…整个半圆旋转,我希望平边是底部。多重绑定没有那么巨大…我试图添加其他属性来实现这一点。它们被注释掉了!:)啊,没注意到他们都被评论掉了。不过,如果能看到这些代码也会很好(然后我可以测试它)。我确实认为,你最好自己做一个新的控制,而不是尝试调整进度条。是的,我就是这么做的!当我看到你的解决方案时,我正要发布更新。谢谢你,凯莉。我还将发布与您类似的解决方案。
public partial class PitchProgressBar : UserControl
{
public static DependencyProperty ProgressIndicatorColorProperty = DependencyProperty.Register("ProgressIndicatorColor", typeof(Brush), typeof(PitchProgressBar), new PropertyMetadata(new PropertyChangedCallback(ProgressIndicatorColorPropertyChanged)));
public static DependencyProperty ProgressIndicatorValueProperty = DependencyProperty.Register("ProgressIndicatorValue", typeof(double), typeof(PitchProgressBar), new PropertyMetadata(new PropertyChangedCallback(ProgressIndicatorValuePropertyChanged)));
private static void ProgressIndicatorColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = d as PitchProgressBar;
if (ctl != null)
{
ctl.pbEllipse.Foreground = (Brush)e.NewValue;
}
}
private static void ProgressIndicatorValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = d as PitchProgressBar;
if (ctl != null)
{
ctl.pbEllipse.Value = (double)e.NewValue;
}
}
public PitchProgressBar()
{
InitializeComponent();
}
public Brush ProgressColor
{
get { return (Brush)GetValue(ProgressIndicatorColorProperty); }
set { SetValue(ProgressIndicatorColorProperty, value); }
}
public double ProgressIndicatorValue
{
get { return (double)GetValue(ProgressIndicatorValueProperty); }
set { SetValue(ProgressIndicatorValueProperty, value); }
}
}
public class FlightGauge : Control
{
private GradientStopCollection _gradStops = new GradientStopCollection();
public static DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(FlightGauge), new FrameworkPropertyMetadata(-100.0, new PropertyChangedCallback(MinValue_Changed)));
public static DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(FlightGauge), new FrameworkPropertyMetadata(100.0, new PropertyChangedCallback(MaxValue_Changed)));
public static DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(FlightGauge), new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(Value_Changed)));
public static DependencyProperty FillColorProperty = DependencyProperty.Register("FillColor", typeof(Color), typeof(FlightGauge), new FrameworkPropertyMetadata(Colors.Blue, new PropertyChangedCallback(FillColor_Changed)));
public Color FillColor
{
get { return (Color)GetValue(FillColorProperty); }
set { SetValue(FillColorProperty, value); }
}
private static void FillColor_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetFillColor();
}
private void SetFillColor()
{
//Put Instance FillColor Property Changed code here
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void Value_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetValue();
}
private void SetValue()
{
CalcTabStops();
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}
private static void MaxValue_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetMaxValue();
}
private void SetMaxValue()
{
CalcTabStops();
}
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetValue(MinValueProperty, value); }
}
private static void MinValue_Changed(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
FlightGauge thisClass = (FlightGauge)o;
thisClass.SetMinValue();
}
private void SetMinValue()
{
CalcTabStops();
}
private void CalcTabStops()
{
_gradStops.Clear();
if (Value > 0)
{
double dLineValue = (1 - Value / MaxValue) /2;
if (dLineValue > 0.49) dLineValue = 0.49;
_gradStops.Add(new GradientStop(Colors.Transparent, 0.500));
_gradStops.Add(new GradientStop(Colors.Transparent, 1.0));
_gradStops.Add(new GradientStop(FillColor, 0.499));
_gradStops.Add(new GradientStop(Colors.Transparent, dLineValue));
_gradStops.Add(new GradientStop(FillColor, dLineValue +0.001));
}
else
{
double dLineValue = 0.5 + (Value / MinValue / 2);
if (dLineValue >= 1) dLineValue = 0.998;
if (dLineValue == 0.5) dLineValue = 0.5001;
_gradStops.Add(new GradientStop(Colors.Transparent, dLineValue +0.01));
_gradStops.Add(new GradientStop(Colors.Transparent, 1.0));
_gradStops.Add(new GradientStop(FillColor, dLineValue));
_gradStops.Add(new GradientStop(Colors.Transparent, 0.5));
_gradStops.Add(new GradientStop(FillColor, 0.501));
}
this.InvalidateVisual();
}
public FlightGauge()
{
BorderBrush = Brushes.Black;
}
protected override void OnRender(DrawingContext drawingContext)
{
Brush brush = null;
if (Value != 0)
{
LinearGradientBrush linBrush = new LinearGradientBrush();
linBrush.StartPoint = new Point(0.5, 0);
linBrush.EndPoint = new Point(0.5, 1);
linBrush.GradientStops = _gradStops;
brush = linBrush;
}
else
{
brush = Brushes.Transparent;
}
double dX = this.ActualWidth / 2;
double dY = this.ActualHeight / 2;
Pen pen = new Pen(BorderBrush, 2);
drawingContext.DrawEllipse(brush, pen, new Point(dX, dY), dX, dY);
drawingContext.DrawLine(pen, new Point(0, dY), new Point(this.ActualWidth, dY));
base.OnRender(drawingContext);
}
}
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:FlightGauge x:Name="fgGauge" Width="200" Height="200" Value="{Binding ElementName=sldValue, Path=Value}" />
<Slider Name="sldValue" Minimum="-100" Maximum="100" Value="0" Grid.Row="1" />
</Grid>