tags:

views:

7383

answers:

4

I'm finding the WPF command parameters to be a limitation. Perhaps that's a sign that I'm using them for the wrong purpose, but I'm still giving it a try before I scrap and take a different tack.

I put together a system for executing commands asynchronously, but it's hard to use anything that requires data input. I know one common pattern with WPF commands is to pass in this. But this will not work at all for asynchronous commands because all the dependency properties are then inaccessible.

I end up with code like this:

<Button Command="{Binding ElementName=servicePage, Path=InstallServiceCommand}">
  <Button.CommandParameter>
     <MultiBinding Converter="{StaticResource InstallServiceParameterConverter}">
        <MultiBinding.Bindings>
           <Binding ElementName="servicePage" Path="IsInstalled"/>
           <Binding ElementName="localURI" Path="Text"/>
           <Binding ElementName="meshURI" Path="Text"/>
           <Binding ElementName="registerWithMesh" Path="IsChecked"/>
         </MultiBinding.Bindings>
      </MultiBinding>
  </Button.CommandParameter>
</Button>

and also need the InstallServiceParametersConverter class (plus InstallServiceParameters).

Anyone see an obvious way to improve upon this?

A: 

You need something that will allow you to request the proper object. Perhaps you need an object just for storing these parameters that your parent object can expose as a property.

Really what you should do is leave the commands synchronous and execute them asynchronously by throwing off a new thread or passing them to a command manager (home rolled).

Orion Adrian
I'm not sure I would consider it an improvement to have to duplicate the CanExecute and exception handling code in every command command I create.Thanks though.
nedruod
+1  A: 

Let me point you to my open source project Caliburn. You can find it at http://caliburn.codeplex.com/. The feature that would most help solve your problem is documented briefly here http://caliburn.codeplex.com/Wiki/View.aspx?title=Action%20Basics&amp;referringTitle=Table%20Of%20Contents.

EisenbergEffect
+1  A: 

Commands are for avoid tight coupling between your UI and program logic. Here, you're trying to get around that so you'll find it painful. You want to have your UI bound to some other object (that contains this data) and your command can then simply make a call to that object. Try searching for MV-V-M, or look at the PRISM example.

At first your suggestion sounded like a very good idea, but then I realized that while that is a very good suggestion for synchronous commands it is a bad idea to pass a shared (global) object to an asynchronous method because it may change mid-execution.
nedruod
A: 

Try using something like MVVM:

Create a class that stores all the data displayed in the current "view" (window, page, whatever makes sense for your application).

Bind your control to an instance of this class.

Have the class expose some ICommand properties, bind the button's Command property to the appropriate property in the data class, you don't need to set the command parameter because all the data has already been transfered to the object using normal everyday data binding.

Have an ICommand derived class that calls back into you object, look at this link for several implementations:

http://dotnet.org.za/rudi/archive/2009/03/05/the-power-of-icommand.aspx

Inside the method called by the command, pack all required data and send it off to a background thread.

Nir