2014-09-02 80 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肯定會節省一天的時間。