Update 2: Displaying background activity in a Silverlight RIA application


Hi folks!  It’s been a little while since I’ve blogged, but fear not, I’m still watching and hoping to blog more in the coming weeks.

In the meantime, it’s been brought to my attention by a few people now that there are a few issues with the Activity control, and I wanted to address them.

  1. Performance – A bit of a mea culpa on my part.  I included a feature for the control that I’ve called “AutoBind”, whereby it would watch for changes to the visual tree of its contents and subscribe to any control that has a property whose name matches “ActivityPropertyName”.  By default, this is great when working with .NET RIA Service’s DomainDataSource, since ActivityPropertyName is “IsBusy” by default, but it also turns out to be a hefty amount of work, constantly searching the visual tree and registering/unregistering event handlers.  This wouldn’t be so bad, except that AutoBind defaults to true, meaning even if you’re not using this functionality, the Activity control is doing the work.  Below, you’ll find a new version of the Activity control that amends the situation, making AutoBind default to false.  This is the only change to the control since my last post on the matter, but I’d love to hear if you have thoughts about the control, this feature, or other requests!
  2. .NET RIA Services’ Business Application Template – So, the .NET RIA Services guys included with their July Preview a project template to help you get started with a RIA Services application.  In this template, they included a dll with the Activity control in it.  A few people have noted that it has a slightly different API than they’re used to seeing with the control, which is due to their use of the original version of the control that I posted (its API has changed a bit since then, and a number of bugs were fixed, including some layout issues).  Anyhoo, feel free to pick up the latest version below!

So there you have it – just a few changes and things to note.  You can find the control here:

Thanks for all the great feedback since I first posted this control.  As usual, let me know if you have questions or issues!

, , , , ,

  1. #1 by Ben Hayat on September 14, 2009 - 9:07 am

    David, I’m glad you found the source of the problem!
    ..Ben

    • #2 by david.poll on September 14, 2009 - 10:41 am

      ;) Yep — someone commented on one of my posts (thanks Jani!) with the same problem and a suggested reason for the problem occurring. I suspected this was the case when we spoke, but wasn’t able to get it to repro. Hopefully this little fix will resolve that issue for most folks.

  2. #3 by Eric on September 14, 2009 - 11:36 am

    Hi,

    Just wanted to say thanks for this control and post a few comments.

    1. I put an activity control on my page, set autobind to false, and did not bind it to anything elsewhere and still it seems to steal the initial focus. I tried to steal it back on the Loaded and LayoutUpdated events but no luck. Any suggestions? The initial focus on my apps is a polish that I feel is essential.

    2. Can I bind multiple controls to one activity control? For instance if I have two domain contexts on my page can I bind them both to the same activity control?

    Right now I just do it like this:
    Binding bdActivity = new Binding(“IsSubmitting”);
    bdActivity.Source = _authService;
    actSSDomainService.SetBinding(Activity.IsActiveProperty, bd);

    Can I just call that SetBinding twice and it will stack them or will it overwrite the first one?

    Thanks

    • #4 by Eric on September 14, 2009 - 12:00 pm

      Just FYI after some tinkering around I found that if I add the Activity control programmatically rather than in XAML this problem goes away.

      • #5 by david.poll on September 14, 2009 - 12:31 pm

        Interesting that this is the case… I’ll have to explore the focus issue a little more.

    • #6 by david.poll on September 14, 2009 - 12:33 pm

      Binding to two things doesn’t work in SL3. What you really want is probably a MultiBinding in WPF world. I can think of a few ways to work around this — might be a good topic for a blog post :) .

  3. #8 by Sean on September 14, 2009 - 1:22 pm

    David,

    Appreciate your feedback and work on this. I’m coming up to speed on Silverlight 3 and RIA Services and have walked throuh Tim’s intro to RIA a number of time.

    I am working on the the “old school” approach to “left pane”, “content pane”, and “right pane” approach to development. Do you suggest having user controls in each “pane” where each has their own activity control or one .xaml page and having an activity control for the whole page?

    Thanks!

    • #9 by david.poll on September 14, 2009 - 1:29 pm

      It really depends on the experience you’re trying to create. In my humble opinion, if your “left pane” or “right pane” have navigation buttons, I wouldn’t block those out with an Activity control unless users navigating would be invalid at those times.

      You’ll want to balance simply binding IsEnabled on certain controls with using the Activity control to actually show your user that something’s going on in the background.

      In general, though, I wouldn’t show activity in more than one place on the screen at a time unless there’s a really good reason to do so. I think it gives the user an overload of redundant information. :) That’s just my opinion though — I’d love to hear how others would do it.

  4. #10 by Kevin on September 15, 2009 - 8:23 am

    Hey David,

    It seems that using this control with a data form still often results in the data form being disabled after the activity control disappears. Any ideas on getting around that?

    • #11 by Kevin on September 18, 2009 - 9:58 am

      David,

      Stefan Olson had a post on his blog about this and it turns out that the problem is not at all with the activity control, but with the data form in the SL3 toolkit. See here:

      http://www.olsonsoft.com/blogs/stefanolson/post/Workarounds-for-dataform-bugs.aspx

      Thanks for the great control, by the way!

      …Kevin

      • #12 by david.poll on September 18, 2009 - 10:07 am

        Good catch. I’ve been scratching my head about it — and figured it was probably on the DataForm end of the spectrum. I’ll ping the DataForm guys to let them know :)

  5. #13 by Patrick on September 15, 2009 - 3:27 pm

    Hello,

    Thanks for this control. As so many others have done, let me express my appreciation as well!

    So, I have a couple comments for others who may have experienced problems and confusion similar to mine, and a question.

    Comment 1) This ActivityControl acts as a container and overrides layout specs on inner controls. For example, I had a TextBlock and ComboBox set to display at a certain position on my Canvas and putting them inside an Activity Control repositioned them to the upper left corner of the screen. The fix for this is to set the position in the declaration of the Activity Control itself.

    Comment 2) It seems that this control can only have one immediate child, so just wrap your inner controls in a StackPanel or some other layout control and you should be fine.

    Question: I want to bind the enabled status of a TextBox to a DomainDataSource’s IsBusy property, but I want the TextBox to be disabled while the DomainDataSource is busy. Unfortunately, using “IsEnabled=”{Binding ElementName=ddsFacilities, Path=IsBusy}” results in exactly the opposite behavior that I’m looking for. (It’s enabled when the DDS is busy and then disable when it is no longer busy…) Is there a different property I can bind to, something like “…Path=NotBusy”?

    Thanks again for the control, and thanks in advance for any help.

    regards,
    Patrick

  6. #15 by Rhett on October 19, 2009 - 9:56 am

    Howdy – thanks very much for this contribution.

    I’m using this with Prism in a tab control and was wondering how you would approach fixing the following: I am restoring a saved view that has multiple tabs that each load data. The last tab loaded gets activated and the Activity indicator displays just fine, but if I switch to another tab that is doing work, the loading indicator for that tab does not get displayed due to the timing of things. I’ll eventually come to a good solution but I thought I would ask for your thoughts on it. Thanks again….

  7. #16 by Rhett on October 19, 2009 - 10:04 am

    Well – as soon as I sent the note I tried something and it worked so simply – in my presenter, right after I set my IsWorking property, I called Arrange() on the Activity control. It is now visible as soon as I switch over to the inactive tab. Thanks again for the control.

    • #17 by david.poll on October 20, 2009 - 2:46 pm

      Glad you managed to work it out! Let me know if you run into anything else.

  8. #18 by Mark Cooper on November 3, 2009 - 3:28 am

    Setting AutoBind=False also gets over an issue with nested controls in a “parent view” using ActivityControl. The parent view “isActive” was being overridden by any child controls that also used ActivityControls.

    Great control, not sure I prefer “wrapping” as opposed to “attributing” though (attached prop).

    Thanks,
    Mark

    • #19 by david.poll on November 17, 2009 - 7:22 pm

      I can understand the desire to avoid wrapping, although there are certain limitations and compromises when you use the attributing method.

      Personally, I get anxious using the “attributing” method, since for something like this it can actually force you to inject things into the visual tree, which could break bindings or otherwise change the logical structure of your application unexpectedly (potentially breaking bindings, etc.).

      Anyway, I think it’s more a matter of preference than anything else. I like the composability of the wrapping method. I often have multiple activity controls wrapping my UI — one with “Loading…”, one with “Submitting…”, one with “Working…”, etc., all bound to different properties.

  9. #20 by Mitch on November 10, 2009 - 12:54 pm

    Hi David,

    Let me first second what everyone is saying… great control, great idea! However, I’m having an issue in some cases getting the content to display right. I’m trying to wrap the content of my page within an activity control but the content is no longer stretching horizontally and veritically.

    I have a hunch it has less to do with your control and more to do with the other elements on the page, and maybe style conflicts, but I’m not sure where to start. Any attempts I’ve made to set the size of the activity control and the size of child elements has failed. Any suggestions would be appreciated.

    • #21 by david.poll on November 17, 2009 - 7:24 pm

      Thanks for the kind words, Mitch! I’m pretty sure your issues are related to using the RIA Services project template, which has a really old build of the control in it. If you download my latest bits, you should be good to go without the layout issues.

  10. #22 by sat on November 17, 2009 - 7:30 am

    Great article , i was searching for the same idea using the keywork silverlight – loading please wait screen. At last found the article good explanation. Had some issues with the RIA template activity dll changed to your dll and everything worked as described. Thanks

    • #23 by david.poll on November 17, 2009 - 7:14 pm

      Yeah, sorry for the confusion due to the RIA Services project template. The next release will hopefully fix this issue (I discussed it with them).

  11. #24 by Aquilax on December 17, 2009 - 1:16 am

    Hi, would it possible to add a bindable (progress) value for the progress bar? That means something like a double value from 0 to 1.

    by Aquilax

(will not be published)