Отображение прогресса с дискретной цветовой заливкой изображения в серебряном свете - PullRequest
1 голос
/ 12 января 2012

В Silverlight я хочу отображать прогресс, например, процесса загрузки в виде последовательности добавочных цветовых заливок на изображении.

Например,

это когда прогресс0: enter image description here

это когда 30%: enter image description here

и 100% полностью цветное изображение: enter image description here

Как я могу контролировать цветзаполнить (я знаю, что это будет с помощью трюка, например, конечного изображения, наложенного на оригинал или что-то еще), чтобы отобразить прогресс?

Моя задача может быть сложной, поскольку изображение представляет собой OpacityMask для кнопки вПроект Windows Phone.

PS Просто, чтобы избежать путаницы, так как обеспокоен конструктивной стороной проблемы.Логика для отслеживания прогресса с некоторыми действиями уже существует.Мне просто нужно выложить презентацию о прогрессе.

Ответы [ 2 ]

2 голосов
/ 12 января 2012

РЕДАКТИРОВАТЬ

Я сделал реализацию. Более подробное объяснение и скачать код можно найти в моем блоге .

C #:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace CustomControls
{
    [TemplatePart(Name="CLIPRECTANGLE", Type=typeof(RectangleGeometry))]
    public class ImageProgressBar : ProgressBar
    {
        public ImageProgressBar()
        {
            this.DefaultStyleKey = typeof(ImageProgressBar);
        }

        public ImageSource Source
        {
            get { return (ImageSource)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageProgressBar), new PropertyMetadata(null));

        public Brush Fill
        {
            get { return (Brush)GetValue(FillProperty); }
            set { SetValue(FillProperty, value); }
        }

        public static readonly DependencyProperty FillProperty =
            DependencyProperty.Register("Fill", typeof(Brush), typeof(ImageProgressBar), new PropertyMetadata(null));

        private RectangleGeometry _clip;

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _clip = this.GetTemplateChild("CLIPRECTANGLE") as RectangleGeometry;
            this.ValueChanged += ImageProgressBar_ValueChanged;
            this.SizeChanged += ImageProgressBar_SizeChanged;
        }

        void ImageProgressBar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateClip();
        }

        void ImageProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            UpdateClip();
        }

        private void UpdateClip()
        {
            if (_clip != null)
            {
                _clip.Rect = new Rect(0, 0, this.ActualWidth, this.ActualHeight * ((this.Value - this.Minimum) / (this.Maximum - this.Minimum)));
            }
        }
    }
}

Шаблон: generic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:CustomControls">
    <Style TargetType="local:ImageProgressBar">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:ImageProgressBar">
                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Margin="{TemplateBinding Margin}"
                            Background="{TemplateBinding Background}"
                            Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}">
                        <Grid>
                            <Image Source="{TemplateBinding Source}"
                                   Stretch="Fill" />
                            <Rectangle Fill="{TemplateBinding Fill}">
                                <Rectangle.OpacityMask>
                                    <ImageBrush ImageSource="{Binding Path=Source, RelativeSource={RelativeSource TemplatedParent}}"
                                                Stretch="Fill" />
                                </Rectangle.OpacityMask>
                                <Rectangle.Clip>
                                    <RectangleGeometry x:Name="CLIPRECTANGLE" />
                                </Rectangle.Clip>
                            </Rectangle>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

Как использовать:

<my:ImageProgressBar Width="100"
                        Height="100"
                        Fill="Red"
                        Source="ProgressBar.png"
                        Minimum="100"
                        Maximum="200"
                        Value="{Binding ElementName=slider1, Path=Value, Mode=TwoWay}" />
<Slider Margin="0"
        Name="slider1"
        VerticalAlignment="Top"
        Minimum="100"
        Maximum="200"
        Value="125" />

Работает как брелок:

Example

Оригинальный ответ

Вы можете создать кисть с линейным градиентом следующим образом:

<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="Black" Offset="0"/>
    <GradientStop Color="Black" Offset="1"/>
    <GradientStop Color="Lime" Offset="1"/>
    <GradientStop Color="Lime" Offset="1"/>
</LinearGradientBrush>

И нарисовать фигуру / символ / текст / что угодно с помощью этой кисти.

Чтобы показать прогресс, просто обновите смещения средних двухgradientstops.Вы можете связать их, чтобы было проще.

Чтобы создать реальный индикатор выполнения: Создайте шаблон для ProgressBar и (multi) привяжите смещения к значению, минимуму и максимуму индикатора выполнения и рассчитайте смещение с помощью(Value - Minimum)/(Maximum - Minimum)

Для использования растрового изображения (PNG):

<Grid HorizontalAlignment="Center"
        VerticalAlignment="Center">
    <Image Source="ProgressBar.png"
            Width="100"
            Height="100" />
    <Rectangle Fill="Lime">
        <Rectangle.OpacityMask>
            <ImageBrush ImageSource="ProgressBar.png" />
        </Rectangle.OpacityMask>
        <Rectangle.Clip>
            <RectangleGeometry Rect="0,25,100,75"/>
        </Rectangle.Clip>
    </Rectangle>
</Grid>

Заменить Rect при изменении прогресса.Чтобы обрезать правильное количество.

Обратите внимание, что то же изображение используется для маски.

0 голосов
/ 12 января 2012

Я сделал пользовательский ProgressBar на днях.Я не собираюсь рассказывать вам точно, как это сделать (потому что я не дизайнер), но это не так сложно.

Создать шаблон

<ControlTemplate x:Key="CustomProgressBarTemplate" TargetType="ProgressBar">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Determinate"/>
                <VisualState x:Name="Indeterminate">
                    <!--Modyify your Storyboard-->
                    <Storyboard RepeatBehavior="Forever">
                        <DoubleAnimation Storyboard.TargetName="IndeterminateGradientFill"
                            Storyboard.TargetProperty="(Shape.Fill).(LinearGradientBrush.Transform).(TransformGroup.Children)[0].X"
                            Duration="00:00:.5" From="0" To="20" />
                        <ObjectAnimationUsingKeyFrames Duration="00:00:00" Storyboard.TargetName="IndeterminateRoot" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Visible</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Duration="00:00:00" Storyboard.TargetName="DeterminateRoot" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <!--Default Root Visuals for either type of ProgressBar-->
        <Border x:Name="ProgressBarTrack" CornerRadius="3" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" />
        <Grid x:Name="ProgressBarRootGrid" >
            <Grid Margin="1">
            </Grid>
            <!-- Beginning of Indeterminate Progress Bar Visuals-->
            <Grid x:Name="IndeterminateRoot" Opacity="0.88" Visibility="Collapsed">
            </Grid>
            <!-- Beginning of Determinate Progress Bar Visuals-->
            <Grid x:Name="DeterminateRoot" Margin="1" >   
            </Grid>
        </Grid>
    </Grid>
</ControlTemplate>

в сетках детерминантных и неопределенных сеток просторисовать изображение с использованием контуров и фигур (Storyboard.TargetProperty = "(Shape.Fill). (LinearGradientBrush.Transform). (TransformGroup.Children) [0] .X" LinearGradientBrush - это кисть, которую я использовал для заливки своих объектовв сетках.)

Примените шаблон

 <ProgressBar Template="{StaticResource CustomProgressBarTemplate}"/>

Вам нужно будет поиграться с дизайном, убедитесь, что вы просто заполните правильный UIElement.Я надеюсь, что это хорошее начало для вас

...