我正在将IList绑定到ListBox。列表中的每个项都执行一个运行后台工作程序的方法。此类具有Progress属性,然后绑定到ListBox的DataTemplate。 progress属性实现了INotifyPropertyChange。
显然,这个想法相对简单:运行多个后台作业并将每个作业的进度报告给用户。我还试图提供其他属性,如“JobStepText”或“IsBusy”。
我正在使用MVVM模式。 ViewModel创建列表并启动异步作业。
这很有效,但是我似乎遇到了同步问题,因为有时工作已经完成,并且on change事件永远不会进入UI。它的行为是完全随机的 - 有时它会在这里和那里发生,有时则不然。
过去几天我一直在谷歌搜索这个,我只是对如何解决这个问题感到难过。
<DataTemplate x:Key="ProgressTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Height="20" Stretch="Uniform" Source="{Binding Failed, Converter={StaticResource ProgressConverter}}"></Image>
<Image Height="20" RenderTransformOrigin="0.5, 0.5" Name="Spinner" Stretch="Uniform" Source="/Aps.SaasHr.M3Migration.Wpf;component/Images/spinner.jpg" Visibility="{Binding Failed, Converter={StaticResource ProgressConverter}}">
<Image.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource Spin360}" />
</EventTrigger.Actions>
</EventTrigger>
</Image.Triggers>
<Image.RenderTransform>
<RotateTransform Angle="0" />
</Image.RenderTransform>
</Image>
<ProgressBar Grid.Column="1" Height="40" IsEnabled="True" Value="{Binding Progress, Mode=OneWay}">
</ProgressBar>
<Border Grid.Column="1" Padding="5" VerticalAlignment="Center" TextBlock.Foreground="Black" TextBlock.FontWeight="Black" TextBlock.FontSize="18">
<StackPanel Orientation="Horizontal" >
<TextBlock FontSize="18" Foreground="White" Text="{Binding Config.ClassType, StringFormat='{}{0}\\'}" ></TextBlock>
<TextBlock FontSize="18" Text="{Binding Config.Name}" ></TextBlock>
<TextBlock Grid.Row="0" Text="{Binding Progress, StringFormat=' (%{0})', Mode=OneWay}"></TextBlock>
<TextBlock VerticalAlignment="Center" Text="{Binding CurrentText}" FontSize="12" Padding="3"></TextBlock>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
以下是启动工人的原因。在像LogText这样的异步操作属性中设置。
public void ProcessAsync(Action<RunWorkerCompletedEventArgs> complete)
{
_worker.RunWorkerCompleted += (o, e) =>
{
IsBusy = false;
if (e.Error != null)
{
Failed = true;
AddLogText("An unexpected error occured: " + e.Error.ToString());
}
else
{
Progress = 100;
Failed = false;
}
OnPropertyChanged("LogText");
complete(e);
};
IsBusy = true;
_worker.RunWorkerAsync();
}
来自列表的子类(具有后台工作者的工作者类)
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
#endregion
public string LogText
{
get { return _logText; }
set
{
_logText = value;
OnPropertyChanged("LogText");
}
}
答案 0 :(得分:0)
我很抱歉这样说,但我认为你目前的做法听起来很可怕。在我看来,数据类型类应该只是数据的持有者。那里不应该有这种功能,特别是没有多线程的功能......你只是在问你现在遇到的麻烦。
而不是那种方法,如何在视图模型中实现多线程功能,只需在后台线程报告时更新集合项的Progress
(以及任何其他属性),例如。通常的方式?如果你这样做,你会发现你遇到的问题要少得多。