【问题标题】:WPF - Viewmodel - Binding errors while refreshing dataWPF - Viewmodel - 刷新数据时绑定错误
【发布时间】:2011-05-05 03:06:04
【问题描述】:

我有一个 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'

当我在视图模型中输入“onRefresh”例程时会发生这种情况。我有一个名为“Current”的可观察集合,我在刷新例程中做的第一件事是清除 Current 集合中的条目。然后我收到大量这些数据错误 17 消息,因为我认为在后台绑定正在尝试更新,现在集合中没有任何内容,直到我重新填充并重新创建可观察集合中的每个条目。

有没有更好的方法来做到这一点?运行时性能似乎不受此影响,但我不喜欢输出窗口中的错误。我发现如果我不清除集合,每次视图模型刷新时它的大小都会翻倍。由于此集合与 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();
    }

【问题讨论】:

    标签: wpf refresh viewmodel


    【解决方案1】:

    您认为绑定错误是由于您的收藏被清除是正确的。由于您没有遇到任何性能损失,因此我不会太担心。

    如果你真的对它们感到恼火,你可以创建一个新的 observable 集合类型来允许你设置新的值。如果您在 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 方法。

    【讨论】:

    • 我真的需要了解更多关于反射器的知识。这看起来很有可能做我需要的事情。感谢您的意见安倍!
    【解决方案2】:

    我知道这个问题已经有一段时间了,但是为我解决此类问题的一种方法是使用 RemoveAt(0) (和/或您需要清除的任何位置),然后将您的数据添加到集合。 Clear() 似乎存在某种时间问题,因为在几个短暂的瞬间,来自数据绑定的调用返回一个空集合,因此输出消息。与更通用的 clear 相比,这可能看起来有点详细,而且可能有些粗鲁,但它确实消除了错误并显着提高了性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-05
      • 2011-08-28
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多