Индикатор выполнения с динамическим обновлением текста и текста

У меня есть progressbar, текст которого изменяется динамически. Я хочу обновить его внешний вид таким образом, что, как только прогресс достигнет текста, цвет текста должен обновиться. Что-то вроде этого. введите описание изображения здесь

Мне нужен текстовый цвет текста (черный), появляющийся над синим фоном, который должен автоматически измениться на белый. Однако текст с белым фоном должен оставаться черным.

Вот один из способов сделать это, используя модифицированную версию Template умолчанию ProgressBars . Он содержит два TextBlocks

  • Первый TextBlock – черный
  • Второй TextBlock – белый. Этот TextBlock имеет ширину полного элемента управления, а Clip установлен на ширину части прогресса

введите описание изображения здесь

Текст ProgressBar является обязательным для свойства Tag . Используется так.

  

MyProgressBarStyle

                                                   

RectConverter

 public class RectConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { double width = (double)values[0]; double height = (double)values[1]; return new Rect(0, 0, width, height); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } 

Вот решение в Silverlight, но его легко преобразовать в WPF.

Я использую линейную gradleиентную кисть для изменения цвета текста в текстовом блоке, я создал пользовательский элемент управления с индикатором выполнения и текстовым блоком, назовем его «SpecialProgressBar»,

Вот XAML:

       

И вот код:

 using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace TestSilverlightApplication { public partial class SpecialProgressBar : UserControl { private Point _textBlockPosition; private readonly LinearGradientBrush _linearGradientBrush; private readonly GradientStop _gradientStop; public SpecialProgressBar() { InitializeComponent(); // will be changing this gradient stop as the progress bar value changes _gradientStop = new GradientStop { Color = Colors.Black, Offset = 0 }; // the default brush we want to start with, // you might want to play with the start point x value to get the effect you want _linearGradientBrush = new LinearGradientBrush { StartPoint = new Point(-0.2, 0.5), EndPoint = new Point(1, 0.5), GradientStops = new GradientStopCollection { _gradientStop, new GradientStop { Color = Colors.Black, Offset = 1 } } }; // set the brush to the text block textBlock.Foreground = _linearGradientBrush; Loaded += new RoutedEventHandler(SpecialProgressBar_Loaded); progressBar.ValueChanged += new RoutedPropertyChangedEventHandler(progressBar_ValueChanged); } private void SpecialProgressBar_Loaded(object sender, RoutedEventArgs e) { // center text block on top of the progress bar _textBlockPosition = new Point(progressBar.Width / 2 - textBlock.ActualWidth / 2, progressBar.Height / 2 - textBlock.ActualHeight / 2); textBlock.SetValue(Canvas.LeftProperty, _textBlockPosition.X); textBlock.SetValue(Canvas.TopProperty, _textBlockPosition.Y); } private void progressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { // print out the value in the text block textBlock.Text = string.Concat(e.NewValue, " of ", progressBar.Maximum); // get the value relative to the size of the progress bar var x = e.NewValue / progressBar.Maximum * progressBar.Width; // if the value is equal to or greater than the position of the text block on the canvas (on the progress bar) // then we want to change the gradient offset and color. if (x >= _textBlockPosition.X) { _gradientStop.Offset += 0.1 * textBlock.ActualWidth / progressBar.Width; _gradientStop.Color = Colors.White; // when we pass the end of the text block we don't need the gradient any more, // replace it with a solid white color if (_gradientStop.Offset >= 1) { textBlock.Foreground = new SolidColorBrush(Colors.White); } } } } } 

Последний шаг – добавить пользовательский элемент управления к странице (или другому пользовательскому элементу управления)

      

И чтобы проверить это, я добавил таймер, чтобы изменить значение строки выполнения:

 using System; using System.Windows.Controls; using System.Windows.Threading; namespace TestSilverlightApplication { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this.Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded); } private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e) { var timer = new DispatcherTimer(); timer.Tick += (s, args) => specialProgressBar.progressBar.Value += 1; timer.Interval = new TimeSpan(1000000); timer.Start(); } } } 

Это выглядит так:

введите описание изображения здесь

Это быстрое и грязное решение, но я думаю, это начало. Надеюсь это поможет.

Хотя я использовал все решение, предоставленное Meleak, но вот как я это сделал.

                          

и вот конвертер

  ///  /// Converts the ProgressBar Fill percentage width to a Rectangle whose width is calculated by multiplying Fill Percentage to Actual Width of control. Height is passed too. /// Note: This converter is used in showing WHITE & BLACK text on progress bar. Also use White textblock next to Black not reverse in XAML. ///  public class ProgressBarFillToRectConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (values != null && values[0] != null && values[1] != null && values[2] != null) { double progressBarFillPercentage = (double)values[0]; double textBlockActualyWidth = (double)values[1]; double textBlockHeight = (double)values[2]; return new Rect(0, 0, progressBarFillPercentage * textBlockActualyWidth, textBlockHeight); // ProgressBarFillWidth is calculated by multiplying Fill // percentage with actual width } return new Rect(0, 0, 0, 0); // Default Zero size rectangle } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } 
Давайте будем гением компьютера.