How to make a loading graphic in WPF XAML?

2019-05-03 06:43发布

问题:

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>

回答1:

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.]



回答2:

You could could create the spinny-loady-thingy and add it to the AdornerLayer of the ListBox.



回答3:

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.



回答4:

You could exploit the IsAsynchronous property of the XmlDataProvider together with the DataChanged event (I didn't try): have a look at the documentation. ;-)



标签: wpf xaml listbox