我有一个MVVM模式测试应用程序正在抛出很多
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'
当我在viewmodel中输入“onRefresh”例程时会发生这种情况。我有一个名为“Current”的可观察集合,我在刷新例程中做的第一件事是清除Current集合中的条目。然后我得到了大量的这些数据错误17消息,因为我认为在后台绑定正在尝试更新,现在集合中没有任何东西,直到我重新填充并重新创建可观察集合中的每个条目。 / p>
有更好的方法吗?运行时性能似乎不受此影响,但我不喜欢输出窗口中的错误。我发现如果我没有清除它的集合,每次viewmodel刷新自己时它的大小只会增加一倍。由于此集合与54个UI元素结合使用,这些元素按索引绑定,因此集合的大小不能加倍,或者所有内容都不会指向正确的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();
}
答案 0 :(得分:1)
您认为绑定错误是由于您的收集被清除所以是正确的。由于您没有遇到任何性能损失,我不会太担心它。
如果您对它们非常恼火,可以创建一个新的可观察集合类型以允许您设置新值。如果你在Reflector中打开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();
}
}
然后,您不是清除数据并一次添加一行,而是调用SetItems方法。
答案 1 :(得分:0)
我知道已经问了这个问题已经有一段时间了,但是我解决这类问题的一种方法是使用RemoveAt(0)(和/或你需要清除的任何位置),然后将数据添加到集合。 Clear()似乎存在某种时序问题,因为对于一些简短的时刻,来自数据绑定的调用返回一个空集合,从而返回输出消息。与更通用的清晰相比,这看起来可能看起来有点细节,也许是野蛮的,但它确实消除了错误并显着提高了性能。