So I have a little WPF XAML that gets the titles of my RSS feed and puts them in a ListBox.
However, it takes about 2 seconds to load.
How can I have put some kind of AJAXy spinning graphic in the ListBox until the data is there?
Here is the code:
<Window x:Class="WpfApplication5.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<StackPanel.Resources>
<XmlDataProvider x:Key="ExternalColors" Source="http://www.tanguay.info/web/rss" XPath="/"/>
</StackPanel.Resources>
<TextBlock Text="RSS Feeds:"/>
<ListBox Name="lbColor" Height="200" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource ExternalColors}, XPath=//item/title}"/>
<TextBlock Text="You selected this feed:"/>
<TextBox
Text="{Binding ElementName=lbColor, Path=SelectedValue}"
Background="{Binding ElementName=lbColor, Path=SelectedValue}">
</TextBox>
</StackPanel>
</Window>
My solution for this is to implement a asynchronous layer between my data and WPF. This totally decouples WPF from any delays on the data side and gives me nice events and properties to trigger and bind against.
I built this on top of the View Model or Presenter Model architecture. I've written a blog post about the basics and a longer piece about my approach to asynchronous View Models.
Here is the XAML of the spinner. In the DataContext
it needs the View Model that does the loading. Depending on its State
, the LoadingIndicator
will make itself visible and collapse again.
<UserControl x:Class="App.WPF.CustomControls.LoadingIndicator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="20"
Width="20">
<UserControl.Style>
<Style TargetType="{x:Type UserControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding State}"
Value="Active">
<Setter Property="Visibility"
Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding State}"
Value="Loading">
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding State}"
Value="Invalid">
<Setter Property="Background"
Value="Red" />
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
<UserControl.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<BeginStoryboard>
<Storyboard TargetName="Rotator"
TargetProperty="Angle">
<DoubleAnimation By="360"
Duration="0:0:2"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Rectangle Stroke="Aqua"
StrokeThickness="2"
Width="10"
Height="10">
<Rectangle.RenderTransform>
<RotateTransform x:Name="Rotator"
Angle="0"
CenterX="5"
CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
</UserControl>
[Source Copyright © 2009 dasz.at OG; This work is licensed under a MIT License.]
You could could create the spinny-loady-thingy and add it to the AdornerLayer of the ListBox.
The following videos are from mix08 and walk you through doing exactly what you want.
Part 1
Part 2
(watch in succession if possible. it is in silverlight but will point you in the right direction.)
Have Fun.
You could exploit the IsAsynchronous
property of the XmlDataProvider
together with the DataChanged
event (I didn't try): have a look at the documentation. ;-)