我正在按照this教程对进度条进行自定义。我得到了与本教程中所示的ProgressBar完全相同的外观。我仍然发布图像:
您可以在ProgressBar的指标部分看到这些白色竖线吗?我想摆脱它们。简而言之,我想要一个简单的指标。
最初,我认为这些酒吧都来自Luna主题。因此,我试图用以下提到的主题一一替换该主题:AeroLight,Classic,Royale。
我尝试了上述主题,因为只有那些主题包含ProgressBarBrushConverter类的定义。
但是我的输出没有任何变化。
因此,我尝试了Aero主题,但在那里我看到Aero不包含ProgressBarBrushConverter的定义。
码:
<Window x:Class="CurvyPB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna"
Title="Curved ProgressBar" Height="400" Width="500">
<Window.Resources>
<ControlTemplate x:Key="PBCurvy" TargetType="{x:Type ProgressBar}">
<Grid>
<Path x:Name="PART_Track" Stroke="{StaticResource BlueGreenRed}" StrokeThickness="5"
Data="F1 M46.802502,0.50000018 C59.803562,0.50000006 71.553123,3.7052743 79.942001, 8.9014616 C88.330879,3.7052746 100.08044,0.5 113.0815,0.50000018 C125.92575, 0.5 137.54851,3.6284194 145.9305,8.6908474 C154.3125,3.6284194 165.93524, 0.50000006 178.7795,0.50000018 C204.35167,0.5 225.082,12.900593 225.082, 28.1975 C225.082,43.494408 204.35167,55.895 178.7795,55.895 C165.93524, 55.895 154.3125,52.766582 145.9305,47.704151 C137.54851,52.766582 125.92575, 55.895 113.0815,55.895 C100.08044,55.895 88.330879,52.689728 79.942001, 47.493538 C71.553123,52.689728 59.803562,55.895 46.802502,55.895 21.230335, 55.895 0.5,43.494408 0.5,28.1975 0.5,12.900593 21.230335,0.5 46.802502, 0.50000018 z"
Stretch="Fill">
<Path.Fill>
<MultiBinding>
<MultiBinding.Converter>
<converter:ProgressBarBrushConverter />
</MultiBinding.Converter>
<Binding Path="Foreground" 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" />
</MultiBinding>
</Path.Fill>
</Path>
<Decorator x:Name="PART_Indicator" />
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid>
<ProgressBar x:Name="CurvyPB" Width="300" Height="60" Template="{StaticResource PBCurvy}" />
</Grid>
</Window>
在后台代码中(仅用于测试):
Private Sub CurvyPB_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Dim a As New DoubleAnimation
a.From = 0
a.To = 100
a.Duration = New TimeSpan(0, 0, 8)
CurvyPB.BeginAnimation(ProgressBar.ValueProperty, a)
End Sub
最佳答案
转换器的源可用here。版权声明仅供参考。
基本上,您需要为使此特别丑陋的进度栏进行更改以填补空白,而这仅仅是这一行:
double blockGap = 0.0; // <-- was 2.0
编辑:添加了
GuidelineSet
,以防止像素对齐间隙(请参阅注释)。整个转换器:
//----------------------------------------------------------------------------
// File: ProgressBarBrushConverter.cs
//
// Description:
// Converts a brush into a DrawingBrush used to display the "block" style
// progress bar
//
// History:
// 06/28/2004 - t-sergin - Created
//
// Copyright (C) 2004,2005 by Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Microsoft.Windows.Themes
{
/// <summary>
/// The ProgressBarBrushConverter class
/// </summary>
public class ProgressBarBrushConverter : IMultiValueConverter
{
/// <summary>
/// Creates the brush for the ProgressBar
/// </summary>
/// <param name="values">ForegroundBrush, IsIndeterminate, Indicator Width, Indicator Height, Track Width
/// <param name="targetType">
/// <param name="parameter">
/// <param name="culture">
/// <returns>Brush for the ProgressBar</returns>
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
//
// Parameter Validation
//
Type doubleType = typeof(double);
if (values == null ||
(values.Length != 5) ||
(values[0] == null) ||
(values[1] == null) ||
(values[2] == null) ||
(values[3] == null) ||
(values[4] == null) ||
!typeof(Brush).IsAssignableFrom(values[0].GetType()) ||
!typeof(bool).IsAssignableFrom(values[1].GetType()) ||
!doubleType.IsAssignableFrom(values[2].GetType()) ||
!doubleType.IsAssignableFrom(values[3].GetType()) ||
!doubleType.IsAssignableFrom(values[4].GetType()))
{
return null;
}
// Conversion
Brush brush = (Brush)values[0];
bool isIndeterminate = (bool)values[1];
double width = (double)values[2];
double height = (double)values[3];
double trackWidth = (double)values[4];
// if an invalid height, return a null brush
if (width <= 0.0 || Double.IsInfinity(width) || Double.IsNaN(width) ||
height <= 0.0 || Double.IsInfinity(height) || Double.IsNaN(height))
{
return null;
}
DrawingBrush newBrush = new DrawingBrush();
// Set the viewport and viewbox to the size of the progress region
newBrush.Viewport = newBrush.Viewbox = new Rect(0, 0, width, height);
newBrush.ViewportUnits = newBrush.ViewboxUnits = BrushMappingMode.Absolute;
newBrush.TileMode = TileMode.None;
newBrush.Stretch = Stretch.None;
DrawingGroup myDrawing = new DrawingGroup();
DrawingContext myDrawingContext = myDrawing.Open();
double drawnWidth = 0.0; // The total width drawn to the brush so far
double blockWidth = 6.0;
double blockGap = 0.0; // <-- was 2.0
double blockTotal = blockWidth + blockGap;
// For the indeterminate case, just draw a portion of the width
// And animate the brush
if (isIndeterminate)
{
int blocks = (int)Math.Ceiling(width / blockTotal);
// The left (X) starting point of the brush
double left = -blocks * blockTotal;
// Only draw 30% of the blocks
double indeterminateWidth = width * .3;
// Generate the brush so it wraps correctly
// The brush is larger than the rectangle to fill like so:
// +-------------+
// [] [] [] __ __ |[] [] [] __ _|
// +-------------+
// Translate Brush =>>
// To have the marquee line up on the left as the blocks are scrolled off to the right
// we need to have the second set of blocks offset from the first by the width of the rect
newBrush.Viewport = newBrush.Viewbox = new Rect(left, 0, indeterminateWidth - left, height);
// Add an animated translate transfrom
TranslateTransform translation = new TranslateTransform();
double milliseconds = blocks * 100; // 100 milliseconds on each position
DoubleAnimationUsingKeyFrames animation = new DoubleAnimationUsingKeyFrames();
animation.Duration = new Duration(TimeSpan.FromMilliseconds(milliseconds)); // Repeat every 3 seconds
animation.RepeatBehavior = RepeatBehavior.Forever;
// Add a keyframe to translate by each block
for (int i = 1; i <= blocks; i++)
{
double x = i * blockTotal;
animation.KeyFrames.Add(new DiscreteDoubleKeyFrame(x, KeyTime.Uniform));
}
// Set the animation to the XProperty
translation.BeginAnimation(TranslateTransform.XProperty, animation);
// Set the animated translation on the brush
newBrush.Transform = translation;
// Draw the Blocks to the left of the brush that are translated into view
// during the animation
// While able to draw complete blocks,
while ((drawnWidth + blockWidth) < indeterminateWidth)
{
// Draw a block
myDrawingContext.DrawRectangle(brush, null, new Rect(left + drawnWidth, 0, blockWidth, height));
drawnWidth += blockTotal;
}
width = indeterminateWidth; //only need to draw 30% of the blocks
drawnWidth = 0.0; //reset drawn width and draw the left blocks
}
// Draw as many blocks
// While able to draw complete blocks,
while ((drawnWidth + blockWidth) < width)
{
var rect = new Rect(drawnWidth, 0, blockWidth, height);
// Snap rect to pixels
GuidelineSet guidelines = new GuidelineSet();
guidelines.GuidelinesX.Add(rect.Left);
guidelines.GuidelinesX.Add(rect.Right);
guidelines.GuidelinesY.Add(rect.Top);
guidelines.GuidelinesY.Add(rect.Bottom);
myDrawingContext.PushGuidelineSet(guidelines);
// Draw a block
myDrawingContext.DrawRectangle(brush, null, rect);
drawnWidth += blockTotal;
}
double remainder = width - drawnWidth;
// Draw portion of last block when ProgressBar is 100% (ie indicatorWidth == trackWidth)
if (!isIndeterminate && remainder > 0.0 && Math.Abs(width - trackWidth) < 1.0e-5)
{
// Draw incomplete block to fill progress indicator area
myDrawingContext.DrawRectangle(brush, null, new Rect(drawnWidth, 0, remainder, height));
}
myDrawingContext.Close();
newBrush.Drawing = myDrawing;
return newBrush;
}
/// <summary>
/// Not Supported
/// </summary>
/// <param name="value">value, as produced by target
/// <param name="targetTypes">target types
/// <param name="parameter">converter parameter
/// <param name="culture">culture information
/// <returns>Nothing</returns>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.