New to Telerik UI for WPF? Download free 30-day trial

Display RadBusyIndicator When UI is Blocked During Layout Operation

Environment

Product Version 2023.3.1010
Product RadBusyIndicator for WPF

Description

How to show RadBusyIndicator for WPF, when the main UI thread is blocked.

Solution

The RadBusyIndicator is a WPF control which means that if something blocks the main UI thread, the indicator will be frozen too. Most commonly it is not displayed at all, or its animation freezes. The purpose of this control is to indicate long operations that happen on a background thread, but it cannot be used to show longer operations related to the WPF layout or rendering. However, there is trick to use RadBusyIndicator in these situations.

To do that, you can display the RadBusyIndicator in a Window opened on a new UI thread. This can happen just before the time consuming layout operation. The closing of the window can be started just after its opening, using the main window's Dispatcher and the DispatcherPriority.ContextIdle setting. This should ensure that the window is closed after the main UI thread is available.

Use this approach only if the main UI thread is blocked. In case you need to busy indicate background operations, use the control in its original setup.

public partial class MainWindow : Window 
{ 
    private Window busyIndicatorWindow; 
 
    public MainWindow() 
    {           
        InitializeComponent();           
    } 
 
    private void OnSetDataButtonClick(object sender, RoutedEventArgs e) 
    { 
        ShowBusyIndicator(); 
 
        // time consuming layout Operation 
        // for example:  
        // this.radGridView.ItemSource = veryBigItemsSource; 
    } 
 
    private void ShowBusyIndicator() 
    { 
        var halfWidth = this.ActualWidth / 2; 
        var halfHeigth = this.ActualHeight / 2; 
        var top = this.Top + (halfHeigth / 2); 
        var left = this.Left + (halfWidth / 2); 
 
        var thread = CreateNewWindowThread(top, left, halfWidth, halfHeigth); 
 
        Dispatcher.BeginInvoke(new Action(() => 
        { 
            var dispatcher = Dispatcher.FromThread(thread); 
            dispatcher.BeginInvoke(new Action(() => { busyIndicatorWindow.Close(); })); 
 
        }), DispatcherPriority.ContextIdle, null); 
    }        
 
    private Thread CreateNewWindowThread(double top, double left, double width, double height) 
    { 
        var thread = new Thread(() => 
        { 
            busyIndicatorWindow = new Window(); 
            busyIndicatorWindow.Content = new RadBusyIndicator() { IsBusy = true }; 
            busyIndicatorWindow.AllowsTransparency = true; 
            busyIndicatorWindow.ShowInTaskbar = true; 
            busyIndicatorWindow.ResizeMode = ResizeMode.NoResize; 
            busyIndicatorWindow.WindowStyle = WindowStyle.None; 
            busyIndicatorWindow.Background = new SolidColorBrush((Color) ColorConverter.ConvertFromString("#5A5FBA7D")); 
            busyIndicatorWindow.Width = width; 
            busyIndicatorWindow.Height = height; 
            busyIndicatorWindow.Top = top; 
            busyIndicatorWindow.Left = left; 
            busyIndicatorWindow.Closed += (s, e) => 
            { 
                busyIndicatorWindow.Dispatcher.InvokeShutdown(); 
            }; 
 
            busyIndicatorWindow.Show();                 
            Dispatcher.Run(); 
        }); 
 
        thread.SetApartmentState(ApartmentState.STA); 
        thread.IsBackground = true; 
        thread.Start(); 
 
        return thread; 
    }       
} 
In this article