2017-02-23 86 views
1

我有兩個數據表「ResultData」和「OutputData」。其中一個接收來自sql查詢的結果,另一個我手動添加行。用戶界面不通過NotifyPropetyChanged更新數據表

ResultData從查詢中獲取結果,適當地更新UI。但是OutputData不。我將鏈接下面的整個方法。我一直堅持這一段時間,它似乎是由於它是異步造成的,但我不知道如何解決它。下面是構造函數和方法

class SqlInterfaceViewModel : INotifyPropertyChanged 
{ 
    private IDBQuery connection; 
    private string sql; 
    private DataTable resultData; 
    private DataTable outputData; 
    public ButtonViewModel Bvm; 
    private string resultStatus; 
    private bool queryRunning; 
    private string elapsedTime; 
    private int sqlCount; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public SqlInterfaceViewModel(IDBQuery connection) 
    { 
     this.connection = connection; 
     outputData = new DataTable(); 
     outputData.Columns.Add("DateTime", typeof(string)); 
     outputData.Columns.Add("Action", typeof(string)); 
     outputData.Columns.Add("Message", typeof(string)); 
     outputData.Columns.Add("Duration", typeof(string)); 

     Bvm = new ButtonViewModel(new ButtonModel(new Action(executeSql))); 
     OutputData.RowChanged += new DataRowChangeEventHandler(Row_Changed); 


    } 
    public bool QueryRunning 
    { 
     get { return queryRunning; } 
     set 
     { 
      if (value != this.queryRunning) 
      { 
       queryRunning = value; 
       OnPropertyChanged("QueryRunning"); 
      } 
     } 
    } 
    public string Sql 
    { 
     get { return sql; } 
     set 
     { 
      if (sql != value) 
       sql = value; 
      OnPropertyChanged("Sql"); 
     } 
    } 
    public DataTable ResultData 
    { 
     get { return resultData; } 
     set 
     { 
      if (resultData != value) 
       resultData = value; 
      OnPropertyChanged("ResultData"); 
     } 
    } 

    public DataTable OutputData 
    { 
     get { return outputData; } 
     set 
     { 
      if (outputData != value) 
       outputData = value; 
      OnPropertyChanged("OutputData"); 
     } 
    } 

    public string ResultStatus 
    { 
     get { return resultStatus; } 
     set 
     { 
      if (resultStatus != value) 
       resultStatus = value; 
      OnPropertyChanged("ResultStatus"); 
     } 
    } 
    private void Row_Changed(object sender, DataRowChangeEventArgs e) 
    { 
     OnPropertyChanged("OutputData"); 
    } 

    private List<string> sqlList(string sql) 
    { 
     List<string> SqlList = sql.Split(';').ToList(); 
     return SqlList; 
    } 

    public async void executeSql() 
    { 
     foreach (string statement in sqlList(sql)) 
     { 
      QueryRunning = true; 
      System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
      DateTime dateTime = DateTime.Now; 
      try 
      { 
       sw.Start(); 
       if (statement.ToUpper().Contains("SELECT")) 
        ResultData = await connection.GetResultSetTask(statement); 
       else 
        sqlCount = await connection.ExecuteUpdate(statement); 
       sw.Stop(); 
       elapsedTime = sw.Elapsed.ToString(@"hh\:mm\:ss\.ffff"); 

       if (statement.ToUpper().Contains("SELECT")) 
        OutputData.Rows.Add(dateTime.ToString(), statement, ResultData.Rows.Count.ToString() + " rows selected", elapsedTime); 
       else if (statement.ToUpper().Contains("UPDATE")) 
        OutputData.Rows.Add(dateTime.ToString(), statement, sqlCount.ToString() + " rows updated successfully", elapsedTime); 
       else if (statement.ToUpper().Contains("INSERT")) 
        OutputData.Rows.Add(dateTime.ToString(), statement, sqlCount.ToString() + " rows inserted successfully", elapsedTime); 
       else if (statement.ToUpper().Contains("DELETE")) 
        OutputData.Rows.Add(dateTime.ToString(), statement, sqlCount.ToString() + " rows deleted successfully", elapsedTime); 
       else 
        OutputData.Rows.Add(dateTime.ToString(), statement, sqlCount.ToString() + " records affected", elapsedTime); 

      } 
      catch (Exception ex) 
      { 
       OutputData.Rows.Add(dateTime.ToString(), sql, sqlCount.ToString() + " records affected", elapsedTime); 
      } 
      finally 
      { 
       QueryRunning = false; 
      } 
     } 
    } 

    public void OnPropertyChanged(string propName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(
       this, new PropertyChangedEventArgs(propName)); 
    } 
} 

我有雙重檢查我的DataTable特性以及綁定在XAML無一不是設置相同。

該方法的ExecuteSQL正在通過ICommand的

public class ButtonViewModel { 
    private bool canExecute; 
    private ICommand clickCommand; 
    private ButtonModel model; 

    public ICommand ClickCommand { get { return clickCommand ?? (clickCommand = new CommandHandler(() => ClickAction(), canExecute)); } } 
    public string ImageUriString { get { return UriStringFactory.GetUriString(model.ImageUriString); } } 
    public string HoverText { get { return model.HoverOverText; } } 

    public ButtonViewModel(ButtonModel model) { 
     canExecute = true; 
     this.model = model; 
    } 

    public void ClickAction() { 
     model.CommandAction(); 
    } 
} 

internal class CommandHandler : ICommand { 
    public event EventHandler CanExecuteChanged; 

    private readonly Action action; 
    private readonly bool canExecute; 

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

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

    public async void Execute(object parameter) { 
     await Task.Run(action); 
    } 
} 
+0

我的解決方案,我想這是從事件觸發解決了這個問題?你可以顯示事件聲明以及如何調用'executeSql()'? – sellotape

+0

也有可能你的更新/插入語句包含文本「選擇」;例如「insert dbo.table1(column1)select 42」? – sellotape

+0

應該指出的是,如果我點擊其中一個列標題,那麼datagrid會在那時更新......我已經爲我的類以及buttonviewmodel添加了構造函數。 –

回答

0

我用Application.Current.Dispatcher.BeginInvoke

生病後下方

class SqlInterfaceViewModel : ViewModelBase 
{ 
    private IDBQuery connection; 
    private string sql; 
    private DataTable resultData; 
    private DataTable outputData; 
    private string resultStatus; 
    private bool queryRunning; 
    private string elapsedTime; 
    private int sqlCount; 
    private string selectedText; 
    private bool cancelSql; 

    public ICommand CommandExecute { get { return new ButtonViewModel(new ButtonModel(new Action(executeSql))).ClickCommand; } } 
    public ICommand CommandCancel { get { return new ButtonViewModel(new ButtonModel(new Action(Cancel))).ClickCommand; } } 
    public ICommand CommandClear { get { return new ButtonViewModel(new ButtonModel(new Action(Clear))).ClickCommand; } } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public SqlInterfaceViewModel(IDBQuery connection){ 
     this.connection = connection; 

     outputData = new DataTable(); 
     outputData.Columns.Add("DateTime", typeof(string)); 
     outputData.Columns.Add("Action", typeof(string)); 
     outputData.Columns.Add("Message", typeof(string)); 
     outputData.Columns.Add("Duration", typeof(string)); 
     cancelSql = false; 

     OutputData.RowChanged += new DataRowChangeEventHandler(Row_Changed); 
    } 
    #region public properties 
    public bool QueryRunning 
    { 
     get { return queryRunning; } 
     set 
     { 
      if (value != this.queryRunning) 
      { 
       queryRunning = value; 
       OnPropertyChanged("QueryRunning"); 
      } 
     } 
    } 
    public string Sql 
    { 
     get { return sql; } 
     set 
     { 
      if (sql != value) 
       sql = value; 
      OnPropertyChanged("Sql"); 
     } 
    } 
    public string SelectedText 
    { 
     get { return selectedText; } 
     set 
     { 
      if (selectedText != value) 
       selectedText = value; 
     } 
    } 
    public DataTable ResultData 
    { 
     get { return resultData; } 
     set 
     { 
      if (resultData != value) 
       resultData = value; 
      OnPropertyChanged("ResultData"); 
     } 
    } 

    public DataTable OutputData 
    { 
     get { return outputData; } 
     set 
     { 
      if (outputData != value) 
       outputData = value; 
      OnPropertyChanged("OutputData"); 
     } 
    } 

    public string ResultStatus 
    { 
     get { return resultStatus; } 
     set 
     { 
      if (resultStatus != value) 
       resultStatus = value; 
      OnPropertyChanged("ResultStatus"); 
     } 
    } 
    private void Row_Changed(object sender, DataRowChangeEventArgs e) 
    { 
     OnPropertyChanged("OutputData"); 
    } 
    #endregion 

    private List<string> sqlList() 
    { 
     List<string> SqlList; 
     if (string.IsNullOrEmpty(selectedText)) 
      SqlList = sql.Split(';').ToList(); 
     else 
      SqlList = selectedText.Split(';').ToList(); 
     return SqlList; 
    } 

    public async Task FormatOutput(string statement, string dateTime, string error) 
    { 
     statement = statement.Trim().Trim(new char[] { '\r', '\n' }); 
     string text = string.Empty; 
      if (string.IsNullOrEmpty(statement) == false) 
     { 
      string substring = statement.ToUpper().Substring(0, statement.IndexOf(' ')); 
      if (string.IsNullOrEmpty(error) != true) 
       text = error; 
      else 
       switch (substring) 
       { 
        case ("SELECT"): 
         text = ResultData.Rows.Count.ToString() + " rows selected"; 
         break; 
        case ("UPDATE"): 
         text = sqlCount + " rows updated"; 
         break; 
        case ("INSERT"): 
         text = sqlCount + " rows inserted"; 
         break; 
        case ("DELETE"): 
         text = sqlCount + " rows deleted"; 
         break; 
        case ("DROP"): 
         text = "Table dropped"; 
         break; 
        case ("CREATE"): 
         text = "Table created"; 
         break; 
       } 
     } 
     await Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => 
     { 
      OutputData.Rows.Add(new object[] { dateTime, statement, text, elapsedTime });})); 
    } 

    public async void executeSql() 
    { 
     QueryRunning = true; 
     foreach (string statement in sqlList()) 
     { 
      if (cancelSql == true) { cancelSql = false; break; } 
      string error = string.Empty; 
      System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); 
      DateTime dateTime = DateTime.Now; 

      if (string.IsNullOrEmpty(statement) == false) 
      { 
       try 
       { 
        if (statement.ToUpper().Substring(0, statement.IndexOf(' ')).Contains("SELECT")) 
         ResultData = await connection.GetResultSetTask(statement); 
        else 
         sqlCount = await connection.ExecuteUpdate(statement); 
       } 

       catch (Exception ex) 
       { 
        error = ex.Message; 
       } 
       finally 
       { 
        sw.Stop(); 
        elapsedTime = sw.Elapsed.ToString(@"hh\:mm\:ss\.ffff"); 
        await FormatOutput(statement, dateTime.ToString(), error); 
        cancelSql = false; 
       } 
      } 
     } 
     QueryRunning = false; 
    } 

    public void Cancel() 
    { 
     connection.cancelQuery(); 
     cancelSql = true; 
    } 
    public void Clear() 
    { Sql = string.Empty; } 
} 
+0

很高興你的工作!請注意,它是更新UI的行更改事件處理程序。使用調度器只是將工作轉到UI線程上,這是'await'上捕獲的上下文將會給你的東西。在你最初的設置中,'OutpData' setter從來沒有被'OutputDat.Rows.Add'命中,所以沒有事件被觸發。儘管你目前的解決方案是解決原始問題的一種方法。 – JSteward

0

叫你現在可能但得到這樣的:它看起來好像executeSql開不設置OutputData,因爲它與ResultData一樣。該方法僅改變OutputData的狀態。在這種情況下,不會引發任何事件。一旦您修改了OutputData並準備好更新用戶界面,您可以簡單地提出更改事件。嘗試添加此:

public async void executeSql() 
{ 
     /** 
     **/ 
     finally 
     { 
      OnPropertyChanged("OutputData"); 
      QueryRunning = false; 
     } 
    } 
} 

注意:你不應該有這個命令處理程序是異步作爲當前上下文將已在AWAIT期間捕獲的任何問題。

相關問題