摆脱进度栏中的白色背景

时间:2014-09-14 20:38:54

标签: c# wpf vb.net

我正在关注this教程,以便为进度条提供自定义外观。我有与ProgressBar完全相同的外观,如教程中所示。我仍然发布图片:

enter image description here

你能在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

1 个答案:

答案 0 :(得分:2)

转换器的来源可用here。版权仅供参考。

基本上你需要改变这个特别丑陋的进度条来填补没有空白只是这一行:

double blockGap = 0.0; // <-- was 2.0

enter image description here

编辑:添加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.