Я новичок в WPF, хотя я и пытался читать столько, сколько я могу, я новичок, которому нужна мудрость, которую мудрец WPF здесь.
У меня есть список просмотра с пользовательским представлением, котороеотобразить тайлвью линейчатых диаграмм.Пользователь выбирает элемент в отдельном списке, это устанавливает источник данных, который будет использоваться в просмотре списка.Моя проблема в том, что пользовательский интерфейс зависает, пока listivew генерирует представление.Вот как выглядит макет:
((извините, я новичок на сайте, поэтому не могу публиковать изображения, но вот ссылка: ScreenShot ))
Источник данных состоит из класса, который содержит некоторые описательные свойства и список списка точек данных (x, y).Tileview берет список списка точек данных и генерирует одну линейную диаграмму для каждого элемента списка, используя список точек данных для рисования линии.
В настоящее время у меня есть источник данных со списком, содержащим 200 элементов, и каждый элемент имеет около200 точек данных (x, y).
Когда я выбираю элемент в левом списке, я использую событие SelectionChanged , чтобы установить свойство ItemsSource моего списка просмотрас новым набором данных.Проблема в том, что пользовательский интерфейс зависает до тех пор, пока не будут сгенерированы все графики.
Я пробовал разные подходы без успеха.Я попытался установить источник данных как асинхронный:
DataSeries="{Binding IsAsync=True, Path=Data}"
Это только помогает нам чуть-чуть, выпуская пользовательский интерфейс до отображения представления.Это означает, что после изменения источника данных он на мгновение заморозит пользовательский интерфейс, затем отпустит его, показывая представление со всеми 200 пустыми диаграммами, и после небольшого обновления представления заполненными диаграммами.
Я также попытался поместитьпривязка внутри потока выглядит следующим образом:
private void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Find the selected itemsource
string runName = (string)ExperimentList.SelectedItem;
ExperimentalRun selectedRun = _experimentRuns.Find(item => item.Name == runName);
//bind datasource thru a new thread
Thread newThread = new Thread(lstProductsNewSource);
newThread.Start(selectedRun);
}
private void lstProductsNewSource(Object selectedRun)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)delegate()
{
lstProducts.ItemsSource = ((ExperimentalRun)selectedRun).RunGraphData;
});
}
lstProducts - это имя списка, в котором есть представление тайлов диаграмм.Свойство RunGraphData указывает на список списка точек данных.
Я надеялся, что это выпустит пользовательский интерфейс, но это не сработало.В этом случае до привязки данных нет процесса, требующего много времени, данные легко доступны в памяти, что требует времени для создания элементов представления и привязки к ним, а не для рендеринга.
КакДополнительные сведения Я хотел бы указать, что диаграммы генерируются пользовательским контролем, и вот как выглядит xml представления плитки:
<local:TileView x:Key="ImageView">
<local:TileView.ItemTemplate>
<DataTemplate>
<StackPanel Width="150" VerticalAlignment="Top">
<local:graph DataSeries="{Binding IsAsync=True, Path=Data}"/>
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Text="{Binding >IsAsync=True, Path=ContainerName}" ></TextBlock>
</StackPanel>
</DataTemplate>
</local:TileView.ItemTemplate>
</local:TileView>
Графический пользовательский контроль - это типичный элемент управления диаграммой, который получает набор данных и связываетit.
Я обращаюсь за советом о том, как сделать так, чтобы мой пользовательский интерфейс реагировал, пока представление списка является обязательным.Вы можете мне помочь?
Редактировать:
Я забыл упомянуть, что пытался использовать виртуализацию в просмотре списка без каких-либо заметных различий:
<ListView Name="lstProducts" View="{StaticResource GridView}" >VirtualizingStackPanel.IsVirtualizing="True" >
</ListView>
Я ожидал, чтоон будет загружать текущее количество элементов в окне и что при прокрутке вниз он начнет загружать новые элементы, но даже когда я использую свойство IsVirtualizing , установленное в значение true, он, кажется, загружает все сразу, с той же задержкой идаже если я прокручиваю вниз, нет никаких дополнительных задержек, создающих впечатление, что все элементы уже присутствуют.
Редактировать 2: На этом сайте я нашел еще один вопрос с ответом, который предоставил тип решения: ссылка
Следуя рекомендациям, приведенным в указанной теме, яизменил мою предыдущую попытку создания потока: от попытки инкапсулировать все событие привязки данных в один фоновый поток до перекачки данных по одному графику за раз, используя преимущества свойств автообновления ObservableCollection.По сути, я создаю пустой источник данных и назначаю его, затем добавляю элементы в источник данных по одному, создавая поток с приоритетом фона каждый раз, когда добавляю точку.Это выглядит так:
private void ExperimentList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Find the selected itemsource
string runName = (string)ExperimentList.SelectedItem;
ExperimentalRun selectedRun = _experimentRuns.Find(item => item.Name == runName);
//create and empty datasource to be filled one item at a time
ExperimentalRun pumpRun = new ExperimentalRun(((ExperimentalRun)selectedRun).Name);
lstProducts.ItemsSource = pumpRun.RunGraphData;
//fill the emtpy source using a new thread per item added
foreach (var item in selectedRun.RunGraphData)
{
PumpExperimentalRunData pump = new PumpExperimentalRunData(pumpRun, item);
Thread newThread = new Thread(PumpAdd);
newThread.Start(pump);
}
}
private void PumpAdd(object PumpExperimentalRunData)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)delegate()
{
((PumpExperimentalRunData)PumpExperimentalRunData).PumpRun.RunGraphData.Add(((PumpExperimentalRunData)PumpExperimentalRunData).Item);
});
}
Этот подход, кажется, работает, но я беспокоюсь, что он создает слишком много потоков (200) каждый раз, когда я меняю источник данных ... То, что я прочитал до сих пор, рекомендует использовать только несколько потоков, и это не подходит как немногие, я думаю. Я хотел бы сделать это по-другому, но у меня нет идей.
Кто-нибудь может увидеть ошибку моих путей или указать лучший подход?