0

我将 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");
        }
    }
4

1 回答 1

0

我很抱歉这么说,但我认为你目前的做法听起来很可怕。在我看来,数据类型类应该只是数据的持有者。那里不应该有任何这种功能,尤其是多线程功能......你只是在问你现在遇到的麻烦。

代替这种方法,如何在视图模型中实现多线程功能,Progress并在后台线程报告回来时更新集合项的(和任何其他属性),例如。以通常的方式?如果你这样做,你会发现你遇到的问题要少得多。

于 2013-10-11T12:46:18.200 回答