【WPF】开启一个线程、xaml绑定属性、绑定命令、取消线程、线程触发UI更新

8 篇文章 0 订阅

主界面

XAML:按钮绑定命令和属性

    <Grid>
		<StackPanel>
			<ProgressBar x:Name="ProgressBar" Height="20" VerticalAlignment="Top" Margin="10 10 10 10" Value="{Binding Progress}"/>
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition/>
					<ColumnDefinition/>
				</Grid.ColumnDefinitions>
				<Button x:Name="StartButton" Grid.Column="0" Content="start!" VerticalAlignment="Top" Margin="10 0 10 10" Command="{Binding ClickCommandStart}" IsEnabled="{Binding StartIsEnabled}" />
				<Button x:Name="CancelButton" Grid.Column="1" Content="cancel!" VerticalAlignment="Top" Margin="10 0 10 10" Command="{Binding ClickCommandCancel}" />
			</Grid>
		</StackPanel>
	</Grid>

主界面交互逻辑:

定义类ViewModel,与主界面上下文绑定。

public class ViewModel : DependencyObject
 DataContext = new ViewModel();//主界面绑定数据上下文模型

定义可以被xaml绑定的命令:

public class CommandHandler : ICommand //可以被xaml绑定的命令
        //UI的start按钮绑定的命令 click from XAML
        public ICommand ClickCommandStart
        {
            get { return new CommandHandler(() => ActionStart(), canExecute); }            
        }
        //UI的取消按钮绑定的命令
        public ICommand ClickCommandCancel
        {
            get { return new CommandHandler(() => ActionCancel(), canExecute); }
        }

定义可以被xaml绑定的属性:

        //DependencyProperty  表示可以通过样式、数据绑定、动画和继承等方法设置的属性
        public DependencyProperty StartIsEnabledProperty;//开始按钮可用属性
        public DependencyProperty ProgressProperty;//进度属性
            //使用指定的属性名称、属性类型和所有者类型注册依赖项属性。
            StartIsEnabledProperty = DependencyProperty.Register("StartIsEnabled", typeof(bool), typeof(ViewModel));
            ProgressProperty = DependencyProperty.Register("Progress", typeof(int), typeof(ViewModel));
        //UI中start按钮绑定的 启用属性
        public bool StartIsEnabled
        {
            get { return (bool)GetValue(StartIsEnabledProperty); }
            set { SetValue(StartIsEnabledProperty, value); }
        }
        //进度条绑定的 进度属性
        public int Progress
        {
            get { return (int)GetValue(ProgressProperty); }
            set { SetValue(ProgressProperty, value * 10); }
        }

在代码里设置属性:

StartIsEnabled = true;
 Progress = 0;

UI更新线程进度:

在线程中定义两个事件:

        public event Action<int> ProcessAdvanced;//汇报进度事件

        public event Action<bool> WorkComplete; //工作完成事件:  bool==true 表示线程被取消。  bool==false 表示线程执行完毕

开启线程时将UI的同步上下文传递给线程:

            Thread thread = new Thread(worker.Work);
            thread.Start(context);//将当前线程同步上下文传递给 worker线程

开启线程前绑定线程事件的处理方法:

            worker.ProcessAdvanced += Worker_ProcessAdvanced;//工作线程进度事件
            worker.WorkComplete += Worker_WorkComplete;//工作线程完成事件

UI的同步上下文获取:

 context = SynchronizationContext.Current;//获取当前线程的同步上下文。传递给工作线程,在工作线程里传递给UI进度信号

工作线程通过UI的同步上下文触发事件:

        //发送事件进度 send event abount progress 在派生类中重写时,将同步消息分派到同步上下文。
        context.Send(OnProgressAdvanced, i);
        //发送关于已完成工作的事件 send event about work done
        context.Send(OnWorkComplete, cancelled);

        //通知UI线程 工作线程进度
        public void OnProgressAdvanced(object progress)
        {
            ProcessAdvanced((int)progress);
        }
        //通知UI线程 工作线程完成
        public void OnWorkComplete(object cancelled)
        {
            WorkComplete((bool) cancelled);
        }

全部代码:

namespace MultithreadingTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ViewModel();//主界面绑定数据上下文模型
        }
    }

    /// <summary>
    /// Button's actions from XAML handler
    /// 按钮的操作 从XAML处理程序
    /// </summary>
    public class CommandHandler : ICommand //可以被xaml绑定的命令
    {
        public event EventHandler CanExecuteChanged;
        private Action action;//命令的操作
        private bool canExecute;//命令是否可执行

        public CommandHandler(Action action, bool canExecute)
        {
            this.action = action;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return canExecute;
        }

        public void Execute(object parameter)
        {
            action();
        }
    }

    /// <summary>
    /// Button's actions and multithreading work event handlers
    /// </summary>
    public class ViewModel : DependencyObject
    {
        // private ICommand click;
        private bool canExecute;
        private Worker worker;
        private SynchronizationContext context;//提供在各种同步模型中传播同步上下文的基本功能。
        //DependencyProperty  表示可以通过样式、数据绑定、动画和继承等方法设置的属性
        public DependencyProperty StartIsEnabledProperty;//开始按钮可用属性
        public DependencyProperty ProgressProperty;//进度属性

        public ViewModel()
        {
            canExecute = true;
            //使用指定的属性名称、属性类型和所有者类型注册依赖项属性。
            StartIsEnabledProperty = DependencyProperty.Register("StartIsEnabled", typeof(bool), typeof(ViewModel));
            ProgressProperty = DependencyProperty.Register("Progress", typeof(int), typeof(ViewModel));

            context = SynchronizationContext.Current;//获取当前线程的同步上下文。传递给工作线程,在工作线程里传递给UI进度信号

            StartIsEnabled = true;
        }

        //UI的start按钮绑定的命令 click from XAML
        public ICommand ClickCommandStart
        {
            get { return new CommandHandler(() => ActionStart(), canExecute); }            
        }
        //UI的取消按钮绑定的命令
        public ICommand ClickCommandCancel
        {
            get { return new CommandHandler(() => ActionCancel(), canExecute); }
        }

        //单击开始操作(第一个线程)  click start action (first thread)
        public void ActionStart()
        {
            Console.WriteLine("Action Start");

            // TODO: how to interact with UI elements?
            StartIsEnabled = false;//禁用开始按钮

            worker = new Worker();
            worker.ProcessAdvanced += Worker_ProcessAdvanced;//工作线程进度事件
            worker.WorkComplete += Worker_WorkComplete;//工作线程完成事件

            Thread thread = new Thread(worker.Work);
            thread.Start(context);//将当前线程同步上下文传递给 worker线程
        }

        //单击取消工作线程 click cancel action (first thread)
        public void ActionCancel()
        {
            StartIsEnabled = true;//开始按钮可用
            worker.Cancel();//取消工作线程
            Console.WriteLine("Action Cancel");
        }

        //与XAML交互的属性 properties to interact with XAML
        //UI中start按钮绑定的 启用属性
        public bool StartIsEnabled
        {
            get { return (bool)GetValue(StartIsEnabledProperty); }
            set { SetValue(StartIsEnabledProperty, value); }
        }
        //进度条绑定的 进度属性
        public int Progress
        {
            get { return (int)GetValue(ProgressProperty); }
            set { SetValue(ProgressProperty, value * 10); }
        }
        
        //工作线程完成 处理函数 event handler (executes in second thread)
        private void Worker_WorkComplete(bool cancelled)//UI线程对于工作线程的完成事件处理方法
        {
            StartIsEnabled = true;

            if (cancelled)
                Progress = 0;

            if (cancelled)
                Console.WriteLine("Work cancelled!");
            else
                Console.WriteLine("Work done.");
        }

        // event handler (starts from second thread)
        private void Worker_ProcessAdvanced(int progress)//UI线程对于工作线程进度更新事件的处理方法
        {
            Progress = progress + 1;    // dirty progressbar delay hack
            Progress = progress;
            Console.WriteLine("Progress handled " + progress.ToString());            
        }
    }


    /// <summary>
    /// Slow methods that shoud be started asynchronously
    /// 应该异步启动的慢方法
    /// </summary>
    public class Worker
    {
        private bool cancelled = false;

        public void Work(object param)
        {
            SynchronizationContext context = (SynchronizationContext) param;

            for (int i = 1; i <= 10; i++)
            {
                if (cancelled)
                    break;

                Console.WriteLine("Working...");
                Thread.Sleep(200);

                //发送事件进度 send event abount progress 在派生类中重写时,将同步消息分派到同步上下文。
                context.Send(OnProgressAdvanced, i);
            }

            //发送关于已完成工作的事件 send event about work done
            context.Send(OnWorkComplete, cancelled);
        }
        //工作线程的取消方法
        public void Cancel()
        {
            cancelled = true;
            Console.WriteLine("Work cancelled!");
        }

        public event Action<int> ProcessAdvanced;//汇报进度事件

        public event Action<bool> WorkComplete; //工作完成事件:  bool==true 表示线程被取消。  bool==false 表示线程执行完毕

        //工作线程操作封装 用于同步上下文的调用 worker actions wrapper voids for sync.context's call
        //通知UI线程 工作线程进度
        public void OnProgressAdvanced(object progress)
        {
            ProcessAdvanced((int)progress);
        }
        //通知UI线程 工作线程完成
        public void OnWorkComplete(object cancelled)
        {
            WorkComplete((bool) cancelled);
        }

    }
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值