2014-09-02 112 views
0

我正在创建一个简单的WPF应用程序,当您单击按钮时,它会通过几个步骤运行,如将文件复制到新位置,转换文件,然后将新文件复制回原始位置。异步更新WPF窗口

这些步骤工作正常,但我希望WPF窗口更新到它所在的步骤,并在运行时隐藏该按钮。

该窗口只有在完成运行我的代码后才会更新。我认为我曾经可以在me.refresh的经典形式上做到这一点,但这对WPF无效。

是什么我可以做的每一步完成后更新窗口?

谢谢

Button1.Visibility = Windows.Visibility.Hidden 

FileCopy("C:\Test.xsf", AppPath & "\Convert\test.xsf") 
Image7.Visibility = Windows.Visibility.Hidden 
Image3.Visibility = Windows.Visibility.Visible 

Program.StartInfo.FileName = xDefs 
Program.StartInfo.Arguments = "/q" 
Program.Start() 
Program.WaitForExit() 
Image5.Visibility = Windows.Visibility.Visible 

FileCopy("AppPath & "\Convert\test.csv, "C:\Test.csv") 
Button1.Visibility = Windows.Visibility.Visible 
+0

[数据绑定(WPF)](http://msdn.microsoft.com/en-us/library/ms750612(v = vs.110).aspx)是您在寻找的。 – pushpraj 2014-09-02 07:52:11

+0

代码示例会有所帮助 - 您至少能告诉我们您是否正在执行MVVM模式后面或后面的代码处理? – kidshaw 2014-09-02 07:52:40

回答

0

为了当你的程序是忙不过来更新UI,你需要使用Dispatcher class添加您的更新请求到UI消息队列。借此同步例如:

public void DoWorkWithFile(string filePath) 
{ 
    CopyFile(filePath); 
    ConvertFile(filePath); 
    CopyFileBack(); 
} 

我们可以使用Dispatcher类来打破这种并在任务之间输送的讯息传回UI:

public void DoWorkWithFile(string filePath) 
{ 
    CopyFile(filePath); 
    RunOnUiThread((Action)delegate { SomeUiTextBlock.Text = "Copied" }); 
    ConvertFile(filePath); 
    RunOnUiThread((Action)delegate { SomeUiTextBlock.Text = "Converted" }); 
    CopyFileBack(); 
    RunOnUiThread((Action)delegate { SomeUiTextBlock.Text = "Copied back" }); 
} 

private object RunOnUiThread(Action method) 
{ 
    return Dispatcher.Invoke(DispatcherPriority.Normal, method); 
} 
0

我知道这是一个VB.NET标记问题但我会继续并分享一个C#解决方案。我希望你知道它足以将它移植到VB。这是第一次,并发布任何东西到计算器,如果它解决了你的问题,请将其标记为答案:-)

你必须首先知道一两件事(实际上更多)的数据绑定。您基本上创建一个视图模型,定义随时间变化的属性并将其绑定到窗口。在这种情况下,您必须定义一个值来跟踪当前操作并让按钮进行控制。

免责声明,我在记事本中写了这个,并没有在visual studio上测试过。注意输入错误。

using System.ComponentModel; 

namespace FileConverter 
{ 

    //define the various states the application will transition to 
    public enum OperationStatus 
    { 
     CopyingFileToNewLocation 
     ConvertingFile, 
     CopyingFileToOriginalLocation 
     OperationCompelete 
    } 

    //Defines the view model that shall be bound to the window. 
    //The view model updates the UI using event notifications. Any control that had enabled 
    //binding will get updated automatically 
    public class ViewModel : INotifyPropertyChanged//This interface defines an event used to raise an event and notify subscribers of a changed in data 
    { 
     private OperationStatus _FileConvertionStatus; 
     public event PropertyChangedEventHandler PropertyChanged; 
     public OperationStatus FileConvertionStatus 
     { 
      get 
      { 
       return _FileConvertionStatus; 
      } 
      set 
      { 
       _FileConvertionStatus=value; 
       //Notify all UIElements/objects that had subscribed to this property that it has changed 
       RaisePropertyChanged(this,"FileConvertionStatus"); 
      } 
     } 

     public void RaisePropertyChanged(object sender,string propertyName) 
     { 
      //check if there is any object that had subscribed to changes of any of the data properties in the view model 
      if(PropertyChanged!=null) 
       PropertyChanged(sender,new PropertyChangedEventArgs(propertyName)); 

     } 

     public void StartFileConvertion(string filePath) 
     { 
      //Any time we change the property 'FileConvertionStatus', an event is raised which updates the UI 
      this.FileConvertionStatus=OperationStatus.CopyingFileToNewLocation; 
      StartCopyingToNewLocation(); //call your copying logic 

      this.FileConvertionStatus=OperationStatus.ConvertingFile; 
      StartFileConvertion(); //call your conversion logic 

      this.FileConvertionStatus=OperationStatus.CopyingFileToOriginalLocation(); 
      CopyFileToOriginalLocation(); //... 

      this.FileConvertionStatus=OperationStatus.OperationCompelete; 
     } 

    } 
} 

//现在的UI部分 在窗口的构造函数,你必须绑定窗口之后该窗口已初始化

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     ViewModel vm=new ViewModel(); 

     //setting the data context property the window implicitly binds the whole window to our view model object 
     this.DataContext=vm; 

     string filePath="c:\file.txt"; 

     //start the file manipulation process 
     vm.StartFileConvertion(filePath); 
    } 
} 

//下一步视图模型我们需要将按钮绑定到位于视图模型中的'FileConvertionStatus'属性。我们不会将按钮绑定到整个视图模型,而只是它感兴趣的属性。在上一代码中将窗口绑定到视图模型后,所有子元素都可以访问此视图模型的公共属性(VM从现在开始)。我们做财产XAML

结合..Button X:NAME = “btnStartFileProcessing” 启用= “{结合FileConvertionStatus}” ......

我们快到了。其中一个缺失。你会注意到'Enabled'属性是一个布尔值。 'FileConvertionStatus'属性是枚举。同样你不能直接将enum分配给布尔值,你需要做一些转换。这是转换器进来的地方。

转换器允许您定义一个属性如何在XAML中转换为不同的属性。在这种情况下,我们只想在文件转换成功时启用按钮。请做一些阅读。

创建类,如下所示:

using System.Windows.Data; 
namespace FileConverter 
{ 
    public class OperationStatusToBooleanConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType,object parameter,System.Globalization.CultureInfo culture) 
     { 
      OperationStatus status=(OperationStatus)value; 
      switch(status) 
      { 
       case OperationStatus.OperationCompelete: 
        return true; //enable the button when everything has been done 
       default: 
        return false;//disable the button as the file processing is underway 
      } 
     } 

     public object ConvertBack(object value, Type targetType,object parameter,System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

接下来的步骤是定义在XAML代码转换器。把它想象为初始化它,尽管它不能离真实:-)更远。它更多地将命名空间导入到xaml.Put下面的App.XAML文件中。在App.XAML文件中做这样的声明使代码全局可见。

的xmlns:MyConverters = “CLR-名称空间:FileConverter”

在Application.Resources XAML标签,声明转换器如下所示

<Application.Resources> 
    <MyConverters:OperationStatusToBooleanConverter x:Key="OperationStatusToBooleanConverter"/> 
</Application.Resources> 

最后一步 重做在绑定代码包含转换器的按钮。

...按钮启用= “{结合FileConvertionStatus,转换器= {StaticResource的OperationStatusToBooleanConverter}}” X:NAME = “btnStartFileProcessing” ......

请注意,我还没有线程优化的代码,主要的问题是所有的工作都是在UI线程上完成的,如果一个操作需要很长时间,可能会导致窗口挂起。

根据MVVM代码标准正确设置绑定所需的工作量很多。这看起来像是过度杀戮,有时实际上是。请记住这一点,但是,一旦UI变得复杂,由于关注点和绑定策略的分离,MVVM肯定会节省一天的时间。