Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > WPF, UWP, WinRT, XAML
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.02.2016, 13:16   #1
DennerV
Пользователь
 
Регистрация: 14.05.2009
Сообщений: 44
Вопрос Вылет при програмной прокрутке DataGrid WPF

Доброго времени суток! Помогите разобраться в непонятной ситуации
Есть DataGrid на форме

Код:
...
        <DataGrid Grid.Row ="4" Name ="Log" ItemsSource="{Binding Mode=OneWay, Path=LogList}" AutoGenerateColumns="False" IsReadOnly="True" HeadersVisibility ="None" >                   
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="Column" Binding ="{Binding Path=.}"></DataGridTextColumn>                
            </DataGrid.Columns>
        </DataGrid>
...
LogList содержит только строки, для быстродействия

Код:
public MtObservableCollection<string> LogList { get; set; }
в него валятся строки при резервном копировании БД.
Код:
private bool startBackup()
        {
            Log.Info("Backup start");
            _logList.Add(curr_time() + "Backup start");
 
            _infoString = new StringBuilder();
            var backup = new FbBackup {
                ConnectionString = _connectionString,
                Verbose = true,
                Options = FbBackupFlags.IgnoreLimbo
            };
 
            backup.BackupFiles.Add(new FbBackupFile(_backupPath + "_" + _strDate + ".fbk", 2048));
            backup.QueryBufferSize = 65535;
            backup.ServiceOutput += service_output;
            backup.Execute();
}
 
      private void service_output(object sender, ServiceOutputEventArgs e){
            _infoString.AppendLine(e.Message);
            lock (_logList) {
                _logList.Add(curr_time() + e.Message);
            }
        }
Чтоб форма не висела, startBackup и service_output выполняется в отдельном потоке
Вроде бы все нормально но DataGrid не прокручивается при добавлении записей

поэтому делаю так:
Код:
public MainLayout(ManagerProvider managerProvider)
        {
            InitializeComponent();
            setBinding(managerProvider);
            _managerProvider = managerProvider;
 
            var myTimer = new Timer {
                Interval = 100,
                Enabled = true
            };
            myTimer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        }
 
      private void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            lock (_managerProvider.LogList) {
                if (Log.Items.Count > 0)
                    Log.Dispatcher.BeginInvoke(new Action(delegate { Log.ScrollIntoView(Log.Items[Log.Items.Count - 1]); }));
            }            
        }
При прокрутке программа вылетает, если использовать _managerProvider.LogList.Collection Changed
вылетает еще раньше
При этом выдает сообщение

Код HTML:
Объект ItemsControl не соответствует своему источнику элементов. Дополнительные сведения см. во внутреннем исключении.
Внутренне исключение

Код HTML:
Информация для разработчиков (для чтения используйте средство визуализации текста):
Данное исключение было создано потому, что генератор для элемента управления "System.Windows.Controls.DataGrid Items.Count:4104" с именем "Log" получил последовательность событий CollectionChanged, которая не согласуется с текущим состоянием коллекции Items.  Обнаружены следующие отличия:
  Накопленное количество 4103 отличается от фактического количества 4104. [Накопленное количество вычисляется по формуле (число при последнем сбросе + кол-во добавлений - кол-во удалений после последнего сброса).]
 
Один или несколько следующих источников могли создать неверные события:
     System.Windows.Controls.ItemContainerGenerator
      System.Windows.Controls.ItemCollection
       System.Windows.Data.ListCollectionView
  *     Telemetria.MtObservableCollection`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
(Источники, которые считаются наиболее вероятной причиной проблемы, помечены звездочкой.)
 
Наиболее распространенные причины: (а) изменение коллекции или ее свойства Count без создания соответствующего события и (б) создание события с неверным параметром индекса или элемента.
 
В трассировке стека исключения описан процесс обнаружения несоответствий, а не процесс их возникновения.  Для своевременного получения исключения задайте значение"High" для присоединенного свойства "PresentationTraceSources.TraceLevel" генератора и перезапустите сценарий.  Один из способов решения этой задачи состоит в выполнении команды, аналогичной следующей:
   System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator, System.Diagnostics.PresentationTraceLevel.High)
из окна интерпретации. Это приведет к запуску логики обнаружения после каждого события CollectionChanged, что замедлит работу приложения.
System.Windows.Controls.DataGrid Items.Count: всякий раз разное
Подскажите в какую сторону копать, никак не пойму в чем дело
Как прокрутка может влиять на обработку CollectionChanged???

Нашел место где возникает ошибка
Код:
public class MtObservableCollection<T> : ObservableCollection<T>
    {
        public MtObservableCollection() { } 
        public MtObservableCollection(IEnumerable<T> list) : base(list)
        {
        
    } 
        public override event NotifyCollectionChangedEventHandler CollectionChanged;
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            NotifyCollectionChangedEventHandler CollectionChanged = this.CollectionChanged;
            if (CollectionChanged != null)
                foreach (NotifyCollectionChangedEventHandler nh in CollectionChanged.GetInvocationList())
                {
                    DispatcherObject dispObj = nh.Target as DispatcherObject;
                    if (dispObj != null)
                    {
                        Dispatcher dispatcher = dispObj.Dispatcher;
                        if (dispatcher != null && !dispatcher.CheckAccess())
                        {
                            dispatcher.BeginInvoke(
                                (Action)(() => nh.Invoke(this,  new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
                                DispatcherPriority.DataBind);
                            continue;
                        }
                    }
                    nh.Invoke(this, e);
                }
        }
    }
в строке (Action)(() => nh.Invoke(this, new NotifyCollectionChangedEventArgs(No tifyCollectionChangedAction.Reset)) ),, подскажите что в ней не так?
DennerV вне форума Ответить с цитированием
Старый 08.02.2016, 13:34   #2
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Цитата:
dispatcher.BeginInvoke
Это выполняет переданный делегат, в котором находится "nh.Invoke", асинхронно. Иными словами есть шанс, что этот CollectionChanged выполнится не вовремя. Уже после того, как другой CollectionChanged отработает.

Попробуйте "dispatcher.BeginInvoke" заменить на "dispatcher.Invoke"
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 08.02.2016, 14:17   #3
DennerV
Пользователь
 
Регистрация: 14.05.2009
Сообщений: 44
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
Иными словами есть шанс, что этот CollectionChanged выполнится не вовремя. Уже после того, как другой CollectionChanged отработает.
Да именно так и происходит

Спасибо, сейчас попробую


Никакого полложительного эффекта

Последний раз редактировалось DennerV; 08.02.2016 в 14:28.
DennerV вне форума Ответить с цитированием
Старый 08.02.2016, 15:48   #4
DennerV
Пользователь
 
Регистрация: 14.05.2009
Сообщений: 44
По умолчанию

Вопрос решен
сделал через ObservableCollection<T>
передал в поток дополнительно Dispatcher и через него вношу изменения в коллекцию
DennerV вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
wpf двумерный массив и datagrid D][mon Помощь студентам 0 20.03.2013 14:43
WPF DataGrid Binding RomanA WPF, UWP, WinRT, XAML 0 28.02.2013 15:54
DataGrid WPF Brodish C# (си шарп) 0 06.01.2013 15:42
Событие в DataGrid WPF ViRTaCe C# (си шарп) 5 09.05.2012 09:34
ADO.Обход ошибок при програмной идентификации. Zo0M БД в Delphi 11 01.08.2009 07:19