Let me explain my problem. Please excuse me for the long question. Here it goes.
I have a View (BusyProviderView)
<Grid>
<xctk:BusyIndicator x:Name="aaa" IsBusy="{Binding IsRunning}" >
<xctk:BusyIndicator.BusyContentTemplate>
<DataTemplate>
<Grid cal:Bind.Model="{Binding}">
<TextBlock Name="Message"/>
</Grid>
</DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>
</xctk:BusyIndicator>
</Grid>
Which has View model:
public class BusyProviderViewModel : PropertyChangedBase, IBusyProvider
{
//two properties with INPC, Message and IsRunning
}
Again I have a Shell view
<Window x:Class="MvvmTest.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ShellView" Height="300" Width="300">
<Grid>
<Button Height="25" x:Name="Run">Run</Button>
<ContentControl x:Name="BusyProvider"/>
</Grid>
Which has a view model
public class ShellViewModel : PropertyChangedBase, IShellViewModel
{
private IBusyProvider busyProvider;
public ShellViewModel(IBusyProvider busy)
{
this.BusyProvider = busy;
}
public IEnumerable<IResult> Run()
{
yield return new DummyOperation(this.BusyProvider);
}
public IBusyProvider BusyProvider
{
get
{
return this.busyProvider;
}
set
{
if (Equals(value, this.busyProvider))
{
return;
}
this.busyProvider = value;
this.NotifyOfPropertyChange(() => this.BusyProvider);
}
}
}
DummyOperation Looks
public class DummyOperation : IResult
{
public IBusyProvider Provider { get; set; }
public DummyOperation(IBusyProvider provider)
{
Provider = provider;
}
public void Execute(ActionExecutionContext context)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (a, b) =>
{
Provider.IsRunning = true;
Provider.Message = "Working";
Thread.Sleep(TimeSpan.FromSeconds(5));
Provider.Message = "Stopping";
Thread.Sleep(TimeSpan.FromSeconds(5));
Provider.IsRunning = false;
};
worker.RunWorkerCompleted += (a, b) =>
{ Completed(this, new ResultCompletionEventArgs()); };
worker.RunWorkerAsync();
}
public event EventHandler<ResultCompletionEventArgs> Completed;
}
Finally I have BootStrapper
public class AppBootstrapper : Bootstrapper<IShellViewModel>
{
private Container container;
protected override void Configure()
{
this.container = new Container();
this.container.Register<IWindowManager,WindowManager>();
this.container.Register<IShellViewModel,ShellViewModel>();
this.container.Register<IBusyProvider, BusyProviderViewModel>();
}
protected override object GetInstance(Type serviceType, string key)
{
return this.container.GetInstance(serviceType);
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return this.container.GetAllInstances(serviceType);
}
protected override void BuildUp(object instance)
{
this.container.Verify();
}
}
Looks Like I have set everything,
But When I try to run it throws an exception.
I am sure the problem is causing by
<DataTemplate>
<Grid cal:Bind.Model="{Binding}">
<TextBlock Name="Message"/>
</Grid>
</DataTemplate>
cal:Bind.Model="{Binding}
Once I remove above statement the program runs without a crash but no binding.
If you look at the Image,
protected override object GetInstance(Type serviceType, string key)
{
return this.container.GetInstance(serviceType);
}
serviceType is passed as a NULL, and key is "Please Wait...." , Where that comes from ??
It seems by default the Extended Toolkit's BusyIndicator
uses the string "Please Wait...."
for the BusyContent
. So inside the DataTemplate
the DataContext
will be the above mentioned string and this causes the confusion and exception in Caliburn.
To fix it you need to set the BusyContent
on the BusyIndicator
to the current DataContext
and it will work:
<xctk:BusyIndicator x:Name="aaa" IsBusy="{Binding IsRunning}"
BusyContent="{Binding}" >
<xctk:BusyIndicator.BusyContentTemplate>
<DataTemplate>
<Grid cal:Bind.Model="{Binding}">
<TextBlock Name="Message"/>
</Grid>
</DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>
</xctk:BusyIndicator>