This is a migrated thread and some comments may be shown as answers.

BusyIndicator not showing when IsBusy set from ListBox item template

2 Answers 190 Views
BusyIndicator
This is a migrated thread and some comments may be shown as answers.
Don
Top achievements
Rank 1
Veteran
Don asked on 16 Nov 2020, 05:25 AM

I have an application with a UserControl that contains a ListBox. The DataTemplate of the ListBox adds a button to each item. The ListBox is inside a BusyIndicator. If I set IsBusy to true from a command bound to a ListBox item the BusyIndicator does not show. If I set IsBusy from the constructor of the UserControl it does show. I am hoping you can tell me why it doesn't show from the command bound from the button.

Here is the xaml for the UserControl:

<UserControl
    x:Class="BusyIndicatorIssue.WidgetView"
    xmlns:local="clr-namespace:BusyIndicatorIssue"
    mc:Ignorable="d"
    d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.DataContext>
        <local:WidgetViewModel/>
    </UserControl.DataContext>
    <UserControl.Resources>
        <local:WidgetView x:Key="topLevelParent"/>
        <DataTemplate x:Key="WidgetListBoxDataTemplate">
            <DockPanel>
                <telerik:RadPathButton
                    DockPanel.Dock="Right"
                    PathGeometry="{telerik:RadGlyph Glyph=}"
                    Command="{Binding Source={StaticResource topLevelParent}, Path=DataContext.RunLongProcessCommand}"
                    CommandParameter="{Binding}"/>
                <TextBlock DockPanel.Dock="Left" FontSize="2" VerticalAlignment="Center" Text="{Binding Name}"/>
            </DockPanel>
        </DataTemplate>
    </UserControl.Resources>
    <telerik:RadBusyIndicator
        BusyContent="{Binding BusyContent}"
        IsBusy="{Binding IsBusy}"
        IsIndeterminate="True">
        <telerik:RadListBox
            x:Name="WidgetListBox" Padding="8"
            ItemsSource="{Binding Widgets, Mode=TwoWay}"
            ItemTemplate="{StaticResource WidgetListBoxDataTemplate}"/>
    </telerik:RadBusyIndicator>
</UserControl>

 

Here is the ViewModel code:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using Telerik.Windows.Controls;
 
namespace BusyIndicatorIssue
{
    public class WidgetViewModel : ViewModelBase
    {
        public WidgetViewModel()
        {
            Widgets = new ObservableCollection<Widget>
            {
                new Widget("Widget 1"),
                new Widget("Widget 2"),
                new Widget("Widget 3"),
                new Widget("Widget 4"),
                new Widget("Widget 5"),
                new Widget("Widget 6"),
                new Widget("Widget 7"),
                new Widget("Widget 8"),
                new Widget("Widget 9")
            };
            RunLongProcessCommand = new DelegateCommand(OnRunLongProcessCommandExecuted);
            //BusyContent = "Doing Something";
            //IsBusy = true;
        }
 
        public DelegateCommand RunLongProcessCommand { get; set; }
        public ObservableCollection<Widget> Widgets { get; set; }
 
        public const string IsBusyPropertyName = "IsBusy";
        private bool _isBusy;
        public bool IsBusy
        {
            get => _isBusy;
            set
            {
                if (_isBusy != value)
                {
                    _isBusy = value;
                    RaisePropertyChanged();
                }
            }
        }
 
        public const string BusyContentPropertyName = "BusyContent";
        private string _busyContent = default!;
        public string BusyContent
        {
            get => _busyContent;
            set
            {
                if (_busyContent != value)
                {
                    _busyContent = value;
                    RaisePropertyChanged();
                }
            }
        }
 
        private void OnRunLongProcessCommandExecuted(object parameter)
        {
            var widget = (Widget)parameter;
            IsBusy = true;
            BusyContent = $"Doing something with {widget}";
            var backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += DoWork;
            backgroundWorker.RunWorkerCompleted += RunWorkerCompleted;
            _ = MessageBox.Show($"About to do something with {widget.Name}.");
            backgroundWorker.RunWorkerAsync(widget);
        }
 
        private void DoWork(object sender, DoWorkEventArgs e)
        {
            var widget = (Widget)e.Argument;
            System.Threading.Thread.Sleep(3000);
            _ = MessageBox.Show($"Done with {widget.Name}.");
        }
 
        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var backgroundWorker = sender as BackgroundWorker;
            if (backgroundWorker is not null)
            {
                backgroundWorker.DoWork -= DoWork;
                backgroundWorker.RunWorkerCompleted -= RunWorkerCompleted;
                InvokeOnUIThread(() => { IsBusy = false; });
            }
        }
    }
}

 

Here is the MainWindow xaml that hosts the UserControl:

<Window x:Class="BusyIndicatorIssue.MainWindow"
        xmlns:local="clr-namespace:BusyIndicatorIssue"
        mc:Ignorable="d"
        Height="300" Width="400"
        Title="MainWindow">
    <DockPanel>
        <local:WidgetView
            DockPanel.Dock="Top"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"/>
    </DockPanel>
</Window>

 

This is the simple model I am using for testing:

namespace BusyIndicatorIssue
{
    public class Widget
    {
        public Widget(string name)
        {
            Name = name;
        }
        public string Name { get; set; }
    }
}

 

I was able to get the BusyIndicator to show by calling a command bound to a button placed directly in the main content of the UserControl. But I really need this application to have the buttons on each ListItem if possible.

 

Regards,

Don

2 Answers, 1 is accepted

Sort by
0
Don
Top achievements
Rank 1
Veteran
answered on 18 Nov 2020, 07:25 AM

Hi,

I am just following up to let you know that I discovered your excellent RadNavigationView. Using that I have redesigned my UI so that I no longer have the above requirement (and my application looks so much nicer).

I think the issue in my original post is probably due to some aspect of xaml binding that I am not getting right.

Thank you,

Don

0
Dilyan Traykov
Telerik team
answered on 18 Nov 2020, 12:48 PM

Hi Don,

I'm glad to hear that using the RadNavigationView control resolved your issue. Please let me know if I can further assist you with anything else.

Regards,
Dilyan Traykov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
BusyIndicator
Asked by
Don
Top achievements
Rank 1
Veteran
Answers by
Don
Top achievements
Rank 1
Veteran
Dilyan Traykov
Telerik team
Share this question
or