#wpf #xaml #progress-bar #taskbar
#wpf #xaml #индикатор выполнения #панель задач
Вопрос:
Я привел простой пример моей проблемы. Существует окно, имеющее привязку DataContext к классу MainWindowViewModel. Окно содержит сетку с кнопкой и индикатором прогресса. Команда кнопки подключается к RelayCommand ViewModel, которая сначала выполняет приращение целочисленного свойства «Процент» от 0 до 100. Панель прогресса показывает прогресс просто отлично! Окно содержит свойство TaskbarItemInfo, и последнее имеет два свойства: значение progress для двойного свойства «Count» и значение ProgressState для свойства TaskbarItemProgressState «State», все свойства в в MainWindowViewModel. TaskbarItemInfo также отлично показывает приращение от 0 до 1.
Но во второй части начального метода прогресс становится неопределенным в течение 5 секунд. Хотя это отлично отображается на панели выполнения, на панели задач этого нет. Я использовал как преобразователь из логического значения в TaskbarItemProgressState в путь свойства ProgressState (IsIndeterminate ), так и привязку к отдельному состоянию свойства, как показано в приведенном ниже коде.
MainWindow.xaml
<Window x:Class="ProgressState.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:ProgressState"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="400">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<local:BoolToProgressStateConverter x:Key="boolToProgressStateConverter"/>
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressValue="{Binding Count, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
ProgressState="{Binding State, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"/>
<!--ProgressState="{Binding IsIndeterminate, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource boolToProgressStateConverter}}"-->
</Window.TaskbarItemInfo>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Start progress" Grid.Row="0" Height="30" Width="100"
Command="{Binding Start}" IsEnabled="{Binding IsEnabled, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
<ProgressBar Grid.Row="1" Height="20" Margin="10 0"
Value="{Binding Percent, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
IsIndeterminate="{Binding IsIndeterminate, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"/>
</Grid>
</Window>
MainWindowViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Shell;
namespace ProgressState
{
public class MainWindowViewModel : ViewModelBase
{
private double count;
private bool isIndeterminate;
private int percent;
private bool isEnabled = true;
private TaskbarItemProgressState state;
public RelayCommand Start { get; set; }
public MainWindowViewModel()
{
Start = new RelayCommand(OnStart, CanStart);
}
public TaskbarItemProgressState State
{
get
{
if (IsIndeterminate)
{
state = TaskbarItemProgressState.Indeterminate;
}
else
{
state = TaskbarItemProgressState.Normal;
}
return state;
}
}
public bool IsEnabled
{
get
{
return isEnabled;
}
set
{
if (value != isEnabled)
{
isEnabled = value;
RaisePropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsIndeterminate
{
get
{
return isIndeterminate;
}
set
{
if (value != isIndeterminate)
{
isIndeterminate = value;
RaisePropertyChanged(nameof(IsIndeterminate));
RaisePropertyChanged(nameof(State));
}
}
}
public int Percent
{
get
{
return percent;
}
set
{
if (value != percent)
{
percent = value;
RaisePropertyChanged(nameof(Percent));
RaisePropertyChanged(nameof(Count));
}
}
}
public double Count
{
get
{
count = Percent / 100d;
return count;
}
}
private bool CanStart()
{
return true;
}
private async void OnStart()
{
IsEnabled = false;
Percent = 0;
await Task.Run(() =>
{
while (Percent != 100)
{
Thread.Sleep(100);
Percent = 2;
}
IsIndeterminate = true;
Thread.Sleep(5000);
IsIndeterminate = false;
});
IsEnabled = true;
}
}
}
BoulToProgressStateConverter.cs
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Shell;
namespace ProgressState
{
class BoolToProgressStateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean)
{
if (boolean == true)
{
return TaskbarItemProgressState.Indeterminate;
}
else if (boolean == false)
{
return TaskbarItemProgressState.Normal;
}
else
{
throw new NotImplementedException();
}
}
return TaskbarItemProgressState.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Есть идеи?
Комментарии:
1. Я использую точно такую же конфигурацию, что и ваша, но с . NET v4.6.1. После переконфигурирования его для использования v4.7.2 (и 4.8) я по-прежнему ничего не получаю на панели задач… По крайней мере, я знаю, что сам код работает. Спасибо за ваше время…
2. Я бы попробовал запустить ваш пример кода на другом компьютере, чтобы подтвердить, что это может быть проблема с вашей системой. Удачи!
3. Я только что попробовал это на машине коллеги, и все работает нормально. Я сделаю еще один комментарий, если мне удастся выяснить, в чем проблема с моей машиной… Еще раз спасибо!
4. Я столкнулся с той же проблемой, моя среда — Win10 WPF .Net5. Оба моих проекта будут делать это, один из проектов, похоже, время от времени работает нормально, и у меня создается впечатление, что это какая-то ошибка.
5. У меня была эта проблема с RDP. По-видимому, есть некоторые оптимизации, которые предотвращают отображение «пульсирования».