2010-11-04 29 views
1

我有一個是折騰了很多WPF - 視圖模型 - 結合的錯誤,同時刷新數據

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'ChuteGroup') from 'Groups' (type 'ChuteGroupsModel'). BindingExpression:Path=Groups[0]; DataItem='MainViewModel' (HashCode=41802290); target element is 'ChuteView' (Name=''); target property is 'DataContext' (type 'Object') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: index' 

當我在視圖模型進入我的「onRefresh」例行這發生在一個MVVM模式測試應用程序。我有一個名爲「Current」的可觀察集合,我在刷新例程中做的第一件事是清除Current集合中的條目。然後我得到這些數據錯誤17個消息的轉換,因爲我覺得在綁定嘗試更新的背景和現在有沒有收藏任何東西,直到我重新填寫並重新創建每次進入觀察集合。

有沒有更好的方法來做到這一點?運行時性能似乎不受此影響,但我不喜歡我的輸出窗口中的錯誤。我發現,如果我沒有清除收藏,那麼每次viewmodel刷新自己時,它的大小都會增加一倍。由於這個集合是與54個的用戶界面元素,它們由索引綁定一起使用時,收集不能在尺寸或一切慣於點加倍到正確的UI元素。

private void FetchData() 
    { 
     ChuteGroupsModel.isDuringRefresh = true; 
     DataSet sqldata = new DataSet(); 
     SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=ScratchPaper;User ID=somecacct;Password=somepassword;Connect Timeout=5"); 
     SqlCommand cmd = new SqlCommand("Select chuteGroup, chuteGroupDef, TotalChutes, UpPackWave, UpColorId, UpPackWaveTS, DownPackWave, DownColorId, DownPackWaveTS from ChuteGroups Order by chuteGroup asc",conn); 
     SqlDataAdapter da = new SqlDataAdapter(cmd); 
     try 
     { 
     da.Fill(sqldata); 

     } 
     catch (Exception Ex){ MessageBox.Show(Ex.ToString());} 


     //DataSet sqldata = this.DataLayer.getDataSet("Select * from AvailableColors Order by ID asc", CommandType.Text, null); 
     foreach (DataRow row in sqldata.Tables[0].Rows) 
     { 
      ChuteGroup group = new ChuteGroup((int)row.ItemArray[0], (string)row.ItemArray[1], (int)row.ItemArray[2], (string)row.ItemArray[3],(string)row.ItemArray[4], (DateTime)row.ItemArray[5], (string)row.ItemArray[6], (string)row.ItemArray[7], (DateTime)row.ItemArray[8]); 
      Add(group); 
     } 
     ChuteGroupsModel.isDuringRefresh = false; 
    } 

private void onRefresh(object sender, System.EventArgs e) 
    { 
     try 
     {  
      if (ChuteGroupsModel.isDuringRefresh) 
      { 
       return; 
      } 
      Refresh(); 
     } 
     catch (Exception ex) 
     { 
      System.Diagnostics.Debug.WriteLine(ex.Message.ToString()); 
     } 
    } 
public void Refresh() 
    { 
     Current.Clear(); //Current is a static reference to my collection 
     FetchData(); 
    } 

回答

1

你是對的,假設綁定錯誤是由於您的收集被清除。由於您沒有遇到任何表現處罰,我不會爲此擔心。

如果你真的被他們激怒,你可以創建一個新的觀察集合類型,允許您設置的新值。如果你破解打開反射器的ObservableCollection類,你會複製執行,並添加一個新的方法,像這樣:

public class ObservableList<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged 
{ 
    // ObservableCollection implementation here 
    ... 

    public void SetItems(IEnumerable<T> items) 
    { 
     this.CheckReentrancy(); 
     base.ClearItems(); 

     int i = 0; 
     foreach (var item in items) 
     { 
      base.InsertItem(i, item); 
      ++i; 
     } 

     this.OnPropertyChanged("Count"); 
     this.OnPropertyChanged("Item[]"); 
     this.OnCollectionReset(); 

    } 
} 

然後,而不是清除數據,並在同一時間將它添加一行,你」 d調用SetItems方法。

+0

我真的得更多地瞭解反射器。這看起來好像有很好的機會做我需要的東西。感謝您的意見Abe! – TWood 2010-11-05 14:42:05

0

我知道它已經有一段時間,因爲這個問題已經被問過,但已經解決了這個類型的問題對我來說是使用RemoveAt移除(0)(和/或任何地方,你需要清除),然後將您的數據的一種方法到收藏。似乎有某種與Clear()在計時問題的幾個瞬間短暫的,用於將數據返回一個空的集合,從而輸出消息從綁定調用。這可能看起來有點細緻,或許與更通用的明確相比有些粗暴,但它確實消除了錯誤並顯着提高了性能。