Does ICommand always requires an object as a parameter? - mvvm

When I implement the ICommand interface, the following methods are created
#region ICommand Members
public bool CanExecute(object parameter)
{
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
}
#endregion
The interesting part is
public void Execute(object parameter)
{
}
Simply because it indicates that it expects 1 parameter. What if I don't need to pass a parameter? In my ViewModel I have the following code
public class DownloadViewModel : BaseViewModel
{
public ICommand BrowseForFile { get; set; }
public string File { get; set; }
public DownloadViewModel()
{
BrowseForFile = new RelayCommand(new Action<object>(OpenDialog));
}
private void OpenDialog(object o)
{
var dialog = new System.Windows.Forms.FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
File = dialog.SelectedPath;
}
}
The OpenDialog method does not require the parameter but it appears as if I have to just so I can satisfy the Interface.
Am I doing this right or have I missed the point?

Yes, ICommand always needs an object and RelayCommand too. If you don't need it, you pass null and don't use it in your method, which is ugly.
I would use Prism's DelegateCommand instead. This exists in a non-generic version, which doesn't take parameters:
Command = new DelegateCommand(DoSomething);
CommandWithParameter = new DelegateCommand<int>(DoSOmethingWithInt);
Its in the PRISM assembly, which you have to download and reference.
using Microsoft.Practices.Prism;
PRISM
Alternatively, use the MVVMLight toolkit, which provides a command class which does basically the same thing. There is no point in using MVVM without a MVVM framework anyway. I can recommend PRISM, also for it's basic stuff like the DelegateCommand or the EventAggregator.

The fact that Execute takes a parameter is irrelevant to the method from your ViewModel. The only thing that affects what parameters OpenDialog needs is your implementation of ICommand.
If your implementation is, for example:
public class MyRandomCommand : ICommand
{
private readonly Action _action;
public MyRandomCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
...
}
Then no parameters will be required for your OpenDialog method, as you can create a command as follows:
public ICommand Command { get { return new MyRandomCommand(OpenDialog); } }
You can, however, require any signature you like for the method you are passing to your command.
The most common, off-the-shelf implementations of RelayCommand can take methods with either 0 or 1 parameter and will be called from Execute appropriately.

Related

How do I combine a Controlled Lifetime relationship type (i.e. Owned<T>) with a delegate factory?

In my application, I have a service that requires a constructor parameter not resolved by Autofac, that I instantiate using a delegate factory:
public class Service
{
public Service(string parameter /*, ... other dependencies */)
{
}
public delegate Service Factory(string parameter);
}
This works great! I really love this feature.
I also like the Controlled Lifetime relationship, so I can let my component depend on a Func<Owned<ISomething>> like this:
public class Component
{
private Func<Owned<ISomething>> _somethingFactory;
/* constructor omitted for brevity */
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory())
{
/* Lots of useful code here */
}
}
}
My problem is that now I want to combine the two. I can't have an instance of Func<Owned<Service>> injected, because it needs that parameter, so my current solution is to abstract the factory away into another service, say IServiceFactory:
public interface IServiceFactory
{
Service Create(string parameter);
}
...implemented as such:
public class ServiceFactory : IServiceFactory
{
private Service.Factory _internalFactory;
public ServiceFactory(Service.Factory internalFactory)
{
_internalFactory = internalFactory;
}
public Service Create(string parameter)
{
return _internalFactory(parameter);
}
}
My component then becomes this:
public class Component
{
Func<Owned<IServiceFactory>> _serviceFactoryFactory;
/* ... */
}
The need for such a field name leaves a bad taste in my mouth to the point that I suspect there must be a cleaner way to handle this case.
Is there another way?
You could change your injected factory to include the string parameter:
private Func<string, Owned<ISomething>> _somethingFactory;
Then you can pass the string to the factory when you want to create a new instance:
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory("my parameter"))
{
/* Lots of useful code here */
}
}
I've created a .NET Fiddle with a small working sample.

Dependency property inside viewmodel in Prism

Is there any way to declare dependency property inside viewmodel? I want to declare a dependency property inside viewmodel and change it's value through command.
public class MyViewModel : Prism.Windows.Mvvm.ViewModelBase
{
public bool IsPaneVisible
{
get { return (bool)GetValue(IsPaneVisibleProperty); }
set { SetValue(IsPaneVisibleProperty, value); }
}
public static readonly DependencyProperty IsPaneVisibleProperty =
DependencyProperty.Register("IsPaneVisible", typeof(bool), typeof(MyViewModel), new PropertyMetadata(0));
public ICommand VisibilityChangeCommand { get; set; }
public MyViewModel()
{
VisibilityChangeCommand = new DelegateCommand(OnVisibilityChange);
}
private void OnVisibilityChange()
{
IsPaneVisible = !IsPaneVisible;
}
}
Problem is, I am getting some compilation error in IsPaneVisible' getter/setter : "GetValue does not exist in the current context". Is there any alternative way to do this?
A DependencyProperty is used on a DependencyObject, an example of this is a UserControl. Prism's ViewModelBase is no DependencyObject, mainly because this type is platform specific. To support binding from a viewmodel, we typically use INotifyPropertyChanged.
Prism implements this interface in the BindableBase base class, from which ViewModelBase derives as well. You define your properties like this:
private string _imagePath;
public string ImagePath
{
get { return _imagePath; }
set { SetProperty(ref _imagePath, value); }
}
If you install the Prism Template Pack Visual Studio extension, you can use the propp code snippet.

mvvmcross touch command binding in android

I'm looking for a way to do a "Touch" command binding between axml and ViewModel, or some else like FocusChanged etc.
A simple "Click" command works fine like so:
local:MvxBind="{'Touch':{'Path':'CameraButtonCommand'}}" />
public IMvxCommand CameraButtonCommand
{
get
{
return new MvxRelayCommand(
() =>
{
RequestNavigate<AugRealityViewModel>(true);
})
;
}
}
However, I've tried other event types for the controll(in this case it's ImageButton) and they are not being processed. When I've checked the events listings in the View Class I see those:
public event EventHandler Click;
public event EventHandler<View.CreateContextMenuEventArgs> ContextMenuCreated;
public event EventHandler<View.FocusChangeEventArgs> FocusChange;
public event EventHandler<View.KeyEventArgs> KeyPress;
public event EventHandler<View.LongClickEventArgs> LongClick;
Only Click event has the general EventHandler attached to it, while other have genericed EventHandlers, and I'm wondering if that's the reason why it doesn't work.
I've also tried to attach a method to those events in the View class getting the proper control by FindViewById method and it works as expected this time around. But somehow I can't do it in the axml through Commands.
Also one more thing. The "Click" event is sending the "EventArgs" object as one of the parameters, and also the object reference. I can see that with ease if I do this behaviour in View Class, but when I do this by binding, I don't see those arguments when I'm processing the Command in ViewModel.
The framework can automatically bind any events which require EventHandler types. However, for any events which require a templated EventHandler (with custom EventArgs) then you are correct - you'll need to include a custom Binding.
The good news is that custom bindings are easy to write and to include.
For example, to bind:
public event EventHandler<View.LongClickEventArgs> LongClick;
you can include something like:
public class LongPressEventBinding
: MvxBaseAndroidTargetBinding
{
private readonly View _view;
private IMvxCommand _command;
public LongPressEventBinding(View view)
{
_view = view;
_view.LongClick += ViewOnLongClick;
}
private void ViewOnLongClick(object sender, View.LongClickEventArgs eventArgs)
{
if (_command != null)
{
_command.Execute();
}
}
public override void SetValue(object value)
{
_command = (IMvxCommand)value;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_view.Click -= ViewOnLongClick;
}
base.Dispose(isDisposing);
}
public override Type TargetType
{
get { return typeof(IMvxCommand); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
Which can be configured in setup using something like:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<View>("LongPress", view => new LongPressEventBinding(view)));
}
Note that you can't write a single class that binds to all the different event types - as the compiler requires you to include the correct Type for the EventArgs. However, you could fairly easily change public class LongClickEventBinding to something like public class CustomEventBinding<TViewType, TEventArgsType> if you wanted to.
With regards to what argument you should pass into the IMvxCommand Execute method, I guess this depends a bit on the method in question, and it also depends on whether you need the ViewModel to support multiple platforms, or whether it is just for Android.

MEF Error when add item to list in constructor method

i write silverlight program very simple.i use Mef and WCF.
this code is MainPageViewModel class that included Commands and properties.
public List<NoOfStudentsDropDownItem> ListNoOfStudent{get;set;}
public MainPageViewModel()
{
InitializList();
}
private void InitializList()
{
ListNoOfStudent.Add(New NoOfStudentsDropDownItem(){DisplayText="1",NoOfStudent=-1});
ListNoOfStudent.Add(New NoOfStudentsDropDownItem(){DisplayText="5",NoOfStudent=5});
}
this is NoOfStudentsDropDownItem class;
public Class NoOfStudentsDropDownItem
{
public string DisplayText{get;set;}
public int NoofStudent{get;set}
}
this is part of App Class.
private void Application_Startup(object sender,StartupEventArgs e)
{
CompositionInitializer.SatisfyImports(this);
MainPage mainpage=new MainPage();
mainpage.DataContext=MainViewModel;
this.RootVisual=mainpage;
}
[Import]
public MainPageViewModel MainViewModel{get;set;}
i haven't error when commented InitializList method.i dont know cause.
You simply forgot to create the list. You declared a property for it, but it is never assigned so it will still be null when you call Add.

AOP using Windsor and bulk registering classes

I am trying to configure an application such that types from assemblyA can be used by my console to allow for logging in an AOP style. The JournalInterceptor will just write out method calls, input and maybe output arguments to a log file or datastore of some kind.
I can register one type at a time but I would like to register all types in one go. Once I get going I may add some filtering to the registered types but I am missing something.
I am trying to use Classes.FromAssemblyContaining but am not sure how to get at an IRegistration instance for the call to WindsorContainer::Register
Any clues?
// otherAssembly.cs
namespace assemblyA
{
public class Foo1 { public virtual void What(){} }
public class Foo2 { public virtual void Where(){} }
}
// program.cs
namespace console
{
using assemblyA;
public class JournalInterceptor : IInterceptor {}
public class Program
{
public static void Main()
{
var container = new Castle.Windsor.WindsorContainer()
.Register(
Component.For<JournalInterceptor>().LifeStyle.Transient,
// works but can't be the best way
Component.For<Foo1>().LifeStyle.Transient
.Interceptors<JournalInterceptor>(),
Component.For<Foo2>().LifeStyle.Transient,
.Interceptors<JournalInterceptor>(),
// how do I do it this way
Classes.FromAssemblyContaining<Foo1>()
.Pick()
.LifestyleTransient()
.Interceptors<JournalInterceptor>()
);
Foo1 foo = container.Resolve<Foo1>();
}
}
}
Implement a Pointcut. In Castle Windsor this is done by implementing the IModelInterceptorsSelector interface.
It would go something like this:
public class JournalPointcut : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel model)
{
return true; // intercept everything - probably not a good idea, though
}
public InterceptorReference[] SelectInterceptors(
ComponentModel model, InterceptorReference[] interceptors)
{
return new[]
{
InterceptorReference.ForType<JournalInterceptor>()
}.Concat(interceptors).ToArray();
}
}
Then register the Interceptor and the Pointcut with the container:
this.container.Register(Component.For<JounalInterceptor>());
this.container.Kernel.ProxyFactory.AddInterceptorSelector(new JournalPointcut());
For in-depth explanation, you may want to see this recording.