WPF - Viewmodel - 刷新数据时绑定错误

发布于 2024-09-30 19:00:28 字数 2545 浏览 3 评论 0原文

我有一个 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();
    }

I have a MVVM pattern test application that is tossing a lot of

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'

This happens when I enter my "onRefresh" routine in the viewmodel. I have an observable collection called "Current" and the first thing I do in the refresh routine is clear the entries from the Current collection. I then get a slew of these data error 17 messages because I think in the background the bindings are trying to update and now there isn't anything in the collection until I re-fill and re-create each entry into the observable collection.

Is there a better way of doing this? Runtime performance doesn't seem to be affected by this but I don't like errors in my output window. I found that if I didn't clear the collection it just doubled in size each time the viewmodel refreshed itself. Since this collection is used in conjunction with 54 UI elements, which are binded by index, the collection can't double in size or everything wont point to the correct UI element.

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();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

掩于岁月 2024-10-07 19:00:28

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

如果您真的对它们感到恼火,您可以创建一个新的可观察集合类型以允许您设置新值。如果您在 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 方法,而不是清除数据并一次添加一行。

You are right in assuming that the binding errors are due to your collection being cleared. As you aren't experiencing any performance penalties, I wouldn't worry about it too much.

If you are really annoyed by them, you can create a new observable collection type to allow you to set the new values. If you crack open the ObservableCollection class in Reflector, you'd copy the implementation, and add one new method like so:

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();

    }
}

Then, instead of clearing your data and adding it one row at a time, you'd call the SetItems method.

把回忆走一遍 2024-10-07 19:00:28

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

I know it's been a while since this question has been asked, but one method that has solved this type of issue for me is using RemoveAt(0) (and/or whatever locations you need cleared) and subsequently Adding your data to the collection. There seems to be some sort of timing issue with Clear() in that for a few brief instants, calls from the bindings for the data returns an empty collection, thus the output messages. This may seem a bit detailed and perhaps brutish in comparison with a more generic clear, but it does remove the errors and noticeably improves performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文