c# - 如何在不阻塞 UI 的情况下在 Binding 中加载控件?

标签 c# wpf multithreading binding

我有这种情况:

我想在 MainWindow 的 ViewModel 中加载一个集合,我有一个大数据,所以当我进入人员集合的幻灯片时,它应该等待完成加载,然后我可以看到完整列表,我有以下内容:

  • 在我的 xaml 代码中:
    <ListView ..... 
    ItemsSource{Binding PeopleList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
    ... />
    
  • 在 View 模式中我有:
    // ...
    private ObservableCollection<Person> _People;
    public ObservableCollection<Person> People
    { get{return _People;} set{ _People = value; RaisePropertyChange("People");}}
    // ...
    

  • 我想在加载第一个完全开始加载第二个之后一个一个地加载所有人员列表......等等而不阻塞主窗口我希望我的窗口看起来像:

    UI Example

    我厌倦了自己做,但我失败了。之前谢谢。

    最佳答案

    存在使用 SynchronizationContext 从另一个线程修改 View 的方法。

    请看这个例子:

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                var sync = SynchronizationContext.Current;
                BackgroundWorker w = new BackgroundWorker();
                w.DoWork+=(_, __)=>
                    {
                        //sync.Post(p => { button.Content = "Working"; }, null);
                        int j = 0;
                        for (int i = 0; i < 10; i++)
                        {
                            j++;
                            sync.Post(p => { button.Content = j.ToString(); }, null);
                            Thread.Sleep(1000);
                        }
                        sync.Post(p => { button.Background = Brushes.Aqua; button.Content = "Some Content"; }, null);
                    };
                w.RunWorkerAsync();
            }
    

    这是观点:
    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Button x:Name="button" Content="Some Content" Click="Button_Click"/>
        </Grid>
    </Window>
    

    此代码多次更新 View (在本例中为按钮)。我认为这解决了您最初的问题。

    ----编辑----

    这是使用这个想法的更好方法:我建议在基本 View 模型中创建这样的方法:
        public void LockAndDoInBackground(Action action, string text, Action beforeVisualAction = null, Action afterVisualAction = null)
        {
            if (IsBusy)
                return;
            var currentSyncContext = SynchronizationContext.Current;
            ActiveThread = new Thread((_) =>
            {                
                currentSyncContext.Send(t =>
                {
                    IsBusy = true;
                    BusyText = string.IsNullOrEmpty(text) ? "Wait please..." : text;
                    if (beforeVisualAction != null)
                        beforeVisualAction();
                }, null);
                action();
                currentSyncContext.Send(t =>
                {
                    IsBusy = false;
                    BusyText = "";
                    if (afterVisualAction != null)
                        afterVisualAction();
                }, null);
            });
            ActiveThread.Start();
        }
    

    这样,任何 subview 模型都可以使用它来执行大量数据处理,并且 UI 不会卡住。 IsBusyBusyText是绑定(bind)到 View 等待消息和等待元素的可见性的 View 模型变量。
    这是在 subview 模型的命令中使用的示例:
      private RelayCommand _SomeCommand;
      public RelayCommand SomeCommand
        {
            get { return _SomeCommand ?? (_SomeCommand = new RelayCommand(ExecuteSomeCommand, CanExecuteSomeCommand)); }
        }
    
        private void ExecuteSomeCommand()
        {
            Action t = ()=> 
            {
                //some action
            };
    
            LockAndDoInBackground(t, "Generating Information...");
        }
    
        private bool CanExecuteSomeCommand()
        {
            return SelectedItem != null;
        }
    

    希望这将成为一个更清楚的例子。

    关于c# - 如何在不阻塞 UI 的情况下在 Binding 中加载控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23109996/

    相关文章:

    c# - ASP MVC - 模型为空

    c# - WPF父menuitem调用子menuitem的命令

    c - 在后台运行线程并使用 OpenMP 继续 main

    php - 如何使我的文件上传后端脚本(PHP、MySQL)线程安全?

    c++ - 多线程单例

    c# - 获取日期范围内的扣除结果

    c# - PetaPoco 存储过程错误 "Incorrect syntax near the keyword ' FROM'。"}

    c# - windows phone 8.1 如何制作确定的圆形进度条

    c# - 在 WPF 中将 Canvas 转换为可写位图的最快方法?

    c# - 如何在 Visual Studio 的 WPF Python 项目中手动创建 App.xaml 文件?