UWP - programmatically display progress bar in ItemTemplate

I am building a Windows Mobile UWP app but I hit the progress bars a bit. I have one working on the first page when starting the application, this is fine, but now I am trying to show it inside a GridView. I will have N number of GridView controls on the screen at any given time and want to display a ProgressBar in each one.

This works great with data binding and the data will show, but when I tried to add an undefined ProgressBar in front of the TextBlock it doesn't seem to show. I can only assume that I am either putting it in the wrong place or I am doing it wrong since my GridView is using GridView.ItemTemplate

.

Here are some screenshots:

No data in the collection

With data in collection

Update with answer

With Justin XL, I was able to get to the bottom of the problem. I was bound to regular clr properties, not DependencyProperty. I changed my code to use MVVM and set the IsLoaded property to handle UI notification. Here is my updated and working code:

ViewModel.cs

public class ViewModel
{
    public string Name { get; set; }
}

      

MainPageViewModel.cs

public class MainPageViewModel : INotifyPropertyChanged
{
    public ObservableCollection<ViewModel> MyData { get; set; } = new ObservableCollection<ViewModel>();

    private bool _isLoaded;

    public bool IsLoaded
    {
        get { return _isLoaded; }
        set
        {
            _isLoaded = value;
            OnPropertyChanged();
        }
    }

    public async Task GetDataAsync()
    {
        // Add items to MyData
        IsLoaded = true;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

      

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        DataContext = new MainPageViewModel();
    }

    public MainPageViewModel Vm => DataContext as MainPageViewModel;

    protected override async void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        await Vm.GetDataAsync();
    }
}

      

MainPage.xaml

<Page
    x:Class="MultiGridProgressBars.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MultiGridProgressBars"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:models="using:MultiGridProgressBars.Models"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <GridView IsHitTestVisible="{x:Bind Vm.IsLoaded, Mode=OneWay}"
            Header="A Grid View"
            HorizontalAlignment="Left"
            x:Name="MyDataListView1"
            ItemsSource="{x:Bind Vm.MyData}"
            Width="164" 
            Margin="10,53,0,53">
            <GridView.ItemTemplate>
                <DataTemplate x:DataType="models:ViewModel">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" HorizontalAlignment="Stretch" TextWrapping="WrapWholeWords">
                            <Run Text="{ x:Bind Name }"></Run>
                        </TextBlock>
                    </Grid>
                </DataTemplate>
            </GridView.ItemTemplate>
            <GridView.ItemContainerStyle>
                <Style TargetType="GridViewItem">
                    <Setter Property="Margin" Value="0 0 0 10"></Setter>
                    <Setter Property="BorderThickness" Value="1"></Setter>
                    <Setter Property="BorderBrush" Value="Blue"></Setter>
                    <Setter Property="Padding" Value="5"></Setter>
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="HorizontalAlignment" Value="Stretch"/>
                    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                    <Setter Property="VerticalAlignment" Value="Stretch"/>
                    <Setter Property="Width" Value="150"></Setter>
                    <Setter Property="Height" Value="80"></Setter>
                </Style>
            </GridView.ItemContainerStyle>
        </GridView>
    </Grid>
</Page>

      

App.xaml

<Application
        x:Class="MultiGridProgressBars.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MultiGridProgressBars"
        xmlns:converters="using:MultiGridProgressBars.Converters"
        RequestedTheme="Light">

    <Application.Resources>
        <converters:InvertIsCheckedVisiblityConverter x:Key="InvertIsCheckedVisiblityConverter" />
        <Style TargetType="GridView">
            <Setter Property="Padding" Value="0,0,0,10" />
            <Setter Property="IsTabStop" Value="False" />
            <Setter Property="TabNavigation" Value="Once" />
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
            <Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
            <Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled" />
            <Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True" />
            <Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
            <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
            <Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
            <Setter Property="IsSwipeEnabled" Value="True" />
            <Setter Property="ItemContainerTransitions">
                <Setter.Value>
                    <TransitionCollection>
                        <AddDeleteThemeTransition />
                        <ContentThemeTransition />
                        <ReorderThemeTransition />
                        <EntranceThemeTransition IsStaggeringEnabled="False" />
                    </TransitionCollection>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <ItemsWrapGrid Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="GridView">
                        <Grid BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}">
                            <ScrollViewer x:Name="ScrollViewer"
                                            AutomationProperties.AccessibilityView="Raw"
                                            BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
                                            HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                                            HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                                            IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
                                            IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
                                            IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
                                            IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
                                            IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
                                            TabNavigation="{TemplateBinding TabNavigation}"
                                            VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                                            VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                                            ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
                                <ItemsPresenter FooterTransitions="{TemplateBinding FooterTransitions}"
                                                FooterTemplate="{TemplateBinding FooterTemplate}"
                                                Footer="{TemplateBinding Footer}"
                                                HeaderTemplate="{TemplateBinding HeaderTemplate}"
                                                Header="{TemplateBinding Header}"
                                                HeaderTransitions="{TemplateBinding HeaderTransitions}"
                                                Padding="{TemplateBinding Padding}" />
                            </ScrollViewer>

                            <ProgressBar x:Name="StatusBar"
                                             Visibility="{Binding IsHitTestVisible, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InvertIsCheckedVisiblityConverter}}"
                                             IsIndeterminate="True" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Application.Resources>
</Application>

      

InvertIsCheckedVisiblityConverter.cs

public class InvertIsCheckedVisiblityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        bool isChecked = (bool) value;
        return isChecked ? Visibility.Collapsed : Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}

      

+4


source to share


1 answer


If you want to ProgressBar

be in the center GridView

, you need to wrap GridView

in Grid

and place ProgressBar

on top GridView

. Something like that -

<Grid>
    <GridView />

    <ProgressBar x:Name="StatusBar"
                 IsIndeterminate="True"></ProgressBar>
</Grid>

      

Of course, you want to show that it is progressing as the data is loaded, so you need a type property IsLoading

that implements INotifyPropertyChanged

and then binds to it IsIndeterminate

.

IsIndeterminate="{Binding IsLoading}"

      


Update



To make it easier, you can also wrap ProgressBar

inside the style GridView

. First, just create a new style based on the standard one, then go to that ControlTemplate

and change the root panel from Border

to Grid

, then just place there ProgressBar

, for example:

>
<ControlTemplate TargetType="GridView">
    <Grid BorderBrush="{TemplateBinding BorderBrush}"
          BorderThickness="{TemplateBinding BorderThickness}"
          Background="{TemplateBinding Background}">
        <ScrollViewer x:Name="ScrollViewer"
                      AutomationProperties.AccessibilityView="Raw"
                      BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
                      HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                      HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                      IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
                      IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
                      IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
                      IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
                      IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
                      TabNavigation="{TemplateBinding TabNavigation}"
                      VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                      VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                      ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
            <ItemsPresenter FooterTransitions="{TemplateBinding FooterTransitions}"
                            FooterTemplate="{TemplateBinding FooterTemplate}"
                            Footer="{TemplateBinding Footer}"
                            HeaderTemplate="{TemplateBinding HeaderTemplate}"
                            Header="{TemplateBinding Header}"
                            HeaderTransitions="{TemplateBinding HeaderTransitions}"
                            Padding="{TemplateBinding Padding}" />
        </ScrollViewer>

        <ProgressBar x:Name="StatusBar"
                     IsIndeterminate="{Binding IsHitTestVisible, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource InvertBoolConverter}}" />
    </Grid>
</ControlTemplate>

      

You will also need a bool property to control loading ProgressBar

. Here we can just use an existing property IsHitTestVisible

. Note that you will also need to invert the value using a converter.

Finally, you can just directly manipulate the loading rendering by doing this -

<GridView IsHitTestVisible="{Binding IsLoaded}" Style="{StaticResource LoadingGridViewStyle}" />

      

+3


source







All Articles