WPF - Viewmodel - ошибки привязки при обновлении данных - PullRequest
1 голос
/ 04 ноября 2010

У меня есть тестовое приложение 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" в viewmodel. У меня есть наблюдаемая коллекция под названием «Текущая», и первое, что я делаю в процедуре обновления, - это очистка записей из текущей коллекции. Затем я получаю множество сообщений об ошибках данных 17, потому что я думаю, что в фоновом режиме привязки пытаются обновить, и теперь в коллекции ничего нет, пока я заново не заполню и заново не создам каждую запись в наблюдаемой коллекции. 1004 *

Есть ли лучший способ сделать это? Это не влияет на производительность во время выполнения, но мне не нравятся ошибки в моем окне вывода. Я обнаружил, что если я не очищаю коллекцию, она просто удваивается в размере каждый раз, когда модель обновления обновляется сама. Поскольку эта коллекция используется в сочетании с 54 элементами пользовательского интерфейса, которые связаны индексом, коллекция не может быть удвоена по размеру или все не будет указывать на правильный элемент пользовательского интерфейса.

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

Ответы [ 2 ]

1 голос
/ 04 ноября 2010

Вы правы, полагая, что ошибки привязки связаны с очисткой вашей коллекции. Поскольку вы не испытываете никаких проблем с производительностью, я бы не стал сильно беспокоиться об этом.

Если они вас действительно раздражают, вы можете создать новый наблюдаемый тип коллекции, чтобы позволить вам устанавливать новые значения. Если вы взломаете класс ObservableCollection в Reflector, вы скопируете реализацию и добавите один новый метод, например, так:

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.

0 голосов
/ 11 октября 2012

Я знаю, что прошло много времени с тех пор, как был задан этот вопрос, но один метод, который решил для меня этот тип проблемы, - это использование RemoveAt (0) (и / или любых других мест, которые вам нужно очистить) и последующее добавление ваших данных Коллекция. Кажется, существует некоторая проблема синхронизации с Clear () в том, что для нескольких кратких мгновений вызовы из привязок для данных возвращают пустую коллекцию, таким образом, выходные сообщения. Это может показаться немного подробным и, возможно, грубым по сравнению с более общим понятием, но оно устраняет ошибки и заметно улучшает производительность.

...