Author |
Share Topic Topic Search Topic Options
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Topic: Does DialogManager have access to the button that is clicked? Posted: 12-Apr-2012 at 11:29am |
We have been moving over our popups to cocktail and we have a question. Question: The DialogManager has access to the IsEnabled property of the button so that it can disable the ok button. Is it possible to tie into the button clicked event too? Example: We have a popup that is an island. We want to be able to pop it up from anywhere and let it save if the user clicks ok or call rejectchanges if the user clicks cancel. It doesnt appear, from what we can see, that the DialogManager allows the view that is being shown to know about the button click. This would require that everywhere we show this box we have implement what happens with ok and what happens when cancelled. Rather we would like the view model that is being shown in the popup to manage its own button clicks.
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 12-Apr-2012 at 12:20pm |
The proper way to do this is to override CanClose in your ViewModel and perform the save, then let your VM close if the save was successful or prevent the closing if the save failed. This approach properly allows you to save asynchronously, wait for the completion and then let the dialog close if successful. Same way you have access to the buttons you have access to the DialogResult to find out what button the user clicked and go down a different path in your CanClose method. Here's a simple example which always lets the dialog close if the user clicked "Cancel", but if they click "Ok", the dialog only closes if IsComplete is true. public override void CanClose(Action<bool> callback)
{
if (!this.DialogHost().DialogResult.Equals(DialogResult.Cancel))
{
callback(IsComplete);
}
else
base.CanClose(callback);
} Here's an example of a CanClose method from TempHire, that performs a Save or RejectChanges. This is not from a dialog, but it's gonna be the same thing for you, except you won't ask the user first if they want to save. public override void CanClose(Action<bool> callback)
{
if (UnitOfWork.HasChanges())
{
var dialogResult =
_dialogManager.ShowMessage("There are unsaved changes. Would you like to save your changes?",
DialogResult.Yes, DialogResult.Cancel, DialogButtons.YesNoCancel);
dialogResult.OnComplete(delegate
{
if (dialogResult.DialogResult == DialogResult.Yes)
{
Busy.AddWatch();
UnitOfWork.CommitAsync(saveResult => callback(true),
_errorHandler.HandleError)
.OnComplete(args => Busy.RemoveWatch());
}
if (dialogResult.DialogResult == DialogResult.No)
{
UnitOfWork.Rollback();
callback(true);
}
if (dialogResult.DialogResult == DialogResult.Cancel)
callback(false);
});
}
else
base.CanClose(callback);
}
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 12-Apr-2012 at 12:37pm |
Thanks Marcel! You have been very quick with answers and we appreciate it.
|
-John Bloom
|
|
JChris
Newbie
Joined: 13-Mar-2012
Location: Kansas
Posts: 8
|
Post Options
Quote Reply
Posted: 13-Apr-2012 at 8:04am |
I notice that CanClose() is being called twice, even in the simplest CanClose() method, like the one mentioned above. Can you elucidate?
|
|
JChris
Newbie
Joined: 13-Mar-2012
Location: Kansas
Posts: 8
|
Post Options
Quote Reply
Posted: 13-Apr-2012 at 8:18am |
In a simplified test, the both CanClose()'s run successfully, however in my implementation (below), the second call errs on the callback(true) with an "Object reference not set". Thanks, Chris public override void CanClose(Action<bool> callback)
{
if (this.DialogHost().DialogResult.Equals(DialogResult.Cancel) == true)
{
base.CanClose(callback);
}
else
{
Save((y) =>
{
CurrentStuff.StuffItems.Reload(IdeaBlade.EntityModel.MergeStrategy.OverwriteChanges);
callback(true);
}
);
}
}
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 13-Apr-2012 at 11:19am |
Better twice than never. :-) Keen observation. That is a bug. I checked in a fix.
|
|
JChris
Newbie
Joined: 13-Mar-2012
Location: Kansas
Posts: 8
|
Post Options
Quote Reply
Posted: 13-Apr-2012 at 11:51am |
Sounds great. thanks!
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 16-Apr-2012 at 7:05am |
Marcel, any idea when version 0.6 will release with the bug fix?
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 16-Apr-2012 at 9:20am |
I haven't set a release date yet. I'm working on something that may or may not require additional enhancements to Cocktail. In the meantime, you can build the assemblies yourself or I can build them and send to you. If you use NuGet, I can generate pre-release NuGet packages that you could deploy to your own local repository.
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 16-Apr-2012 at 10:08am |
We use NuGet so that would be the easiest for us.
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 17-Apr-2012 at 6:05pm |
John, You can download the pre-release NuGet packages for Cocktail and CocktailContrib from the following link.
https://skydrive.live.com/redir.aspx?cid=b37183c914f0fbe8&resid=B37183C914F0FBE8!210&parid=B37183C914F0FBE8!208&authkey=!AFFzCj8dMKSPTNg
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 18-Apr-2012 at 8:21am |
Thanks Marcel. I installed it this morning and we are moving forward.
|
-John Bloom
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 18-Apr-2012 at 12:39pm |
Because we have logic in the can close there is a little pause before the dialog window disappears. If the user clicks the ok button a second time the dialog manager throws an exception. System.NotSupportedException: TryClose requires a parent IConductor or a view with a Close method or IsOpen property. at Caliburn.Micro.Screen.<GetViewCloseAction>b__11() at Caliburn.Micro.Screen.<TryClose>b__1b() at Caliburn.Micro.Execute.<>c__DisplayClass2.<InitializeWithDispatcher>b__0(Action action) at Caliburn.Micro.Execute.OnUIThread(Action action) at Caliburn.Micro.Screen.TryClose() at Cocktail.DialogHostBase.Close(DialogButton dialogButton) In the TemphHire app the view closes too fast to repo this. I added this code to PhoneTypeSelectorViewModel to simulate a canclose that runs async: public override void CanClose(System.Action<bool> callback)
{
System.Threading.Thread.Sleep(1000);
callback(true);
} If you click on the ok button a few times while the window is sleeping you will see the error. I got around this by disabling all of the buttons when the CanClose is called but that is a lot of maintenance code per view model. Maybe the dialog manager can do it automatically?
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 18-Apr-2012 at 2:32pm |
I have to think about this. Disabling the buttons is easy. Enabling them again if the dialog box doesn't close is a whole other story. The asynchronous nature of the closing makes this very difficult to handle outside of the CanClose where the developer knows when the buttons should be enabled again.
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 19-Apr-2012 at 6:46am |
Thinking about it more, it would be fine if the buttons didn't disable as long as they didnt throw the exception when they were clicked the second time.
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 19-Apr-2012 at 11:26am |
Neither is a quick fix. When a button is clicked it simply calls TryClose on the outer VM, from that point on it's all Caliburn.Micro. To change the current behavior I have to look into replacing the default closing strategy or worst case implementing my own conductor from scratch. I can't make any promises at this point. Have a bunch of higher prioritiy items on my plate currently. For now the workaround is to disable the buttons yourself or better yet, display a busy indicator. If there's a noticable lag to the user, you should probabaly indicate that the application is doing something.
|
|