Моя ситуация примерно похожа на этого парня за исключением того, что мне не нужны уведомления об изменениях прямо сейчас
У меня есть приложение WPF, отображающее иерархию. Дочерние элементы для каждого узла извлекаются с использованием запроса LinqToSql. Приложение отлично работает, когда есть одна нить.
Теперь я бы хотел немного ускорить процесс, асинхронно загружая детей. Запустите поток, чтобы выполнить выборку из БД, по завершении создайте соответствующие узлы дерева для дочерних элементов.
<HierarchicalDataTemplate DataType="{x:Type viewmodels:NodeDM}" ItemsSource="{Binding Path=Children}">
После вчерашнего разгрома я обнаружил, что привязка данных WPF позволяет это через свойство IsAsync
в привязке. Поэтому я сделал следующее изменение
<HierarchicalDataTemplate .. ItemsSource="{Binding Path=Children, IsAsync=True}">
Теперь его беспредел, начальная группа узлов проходит через огонь, прежде чем исключения начнут бунт. Вставить первый здесь ...
System.Windows.Data Error: 16 : Cannot get 'Children' value (type 'ObservableCollection`1') from '' (type 'NodeDM'). BindingExpression:Path=Children; DataItem='NodeDM' (HashCode=29677729); target element is 'TreeViewItem' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Specified cast is not valid.
at System.Data.SqlClient.SqlBuffer.get_Int32()
at System.Data.SqlClient.SqlBuffer.get_Value()
at System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32 i)
<snipped around 20-30 lines>
at System.Data.Linq.Table`1.GetEnumerator()
at System.Data.Linq.Table`1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator()
at System.Linq.Lookup`2.CreateForJoin(IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
at System.Linq.Enumerable.<JoinIterator>d__61`4.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at ICTemplates.Models.NodeDM.Load_Children()
at ICTemplates.Models.NodeDM.get_Children()
Другие включают
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
У меня деформированное дерево, в котором некоторые узлы не удалось загрузить. У меня есть одноэлементный экземпляр всемогущего класса LinqToSql DataContext, который общается с БД. Поэтому я попытался установить блокировку, чтобы несколько рабочих потоков не обращались к ней одновременно ... но не повезло.
partial class Node
{
public IEnumerable<Segment> Children
{
lock (MyDatabaseDataContext.m_lockObject)
{
return // LINQ Query to join 2 tables and return a result
}
}
Отмена изменения IsAsync снова делает все хорошо.
Почему свойство IsAsync портит LinqToSql? WPF Treeview достаточно, чтобы нормальные люди вырывали свои волосы.