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:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
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