For example I have this property in my ViewModel.
public IStorageFolder CurrentFolder
{
get
{
return _currentFolder;
}
set
{
Set(ref _currentFolder, value);
CommandBindings[nameof(NavigateCommand)].Execute(Model);
}
}
private IStorageFolder _currentFolder = null;
CommandBindings.cs
public class CommandBindings
{
...
public ICommand this[string name]
{
get
{
return GetCommandByName(name);
}
}
public ICommand GetCommandByName(string name)
{
...
}
}
Navigate.cs
public class NavigateCommand : ExplorerCommand
{
public override bool CanExecute(IExplorerModel model)
{
return true;
}
public override async Task ExecuteAsync(IExplorerModel model)
{
....
}
}
CommandBindingsProvider.cs
public class CommandBindingsProvider : ICommandBindingsProvider
{
public CommandBindings GetBindings()
{
var commandInfos = new List<CommandInfo>();
var serviceLocator = ServiceLocator.Current;
var explorerCommandTypes = GetExplorerCommandTypes();
foreach (var commandType in explorerCommandTypes)
{
var command = serviceLocator.GetInstance(commandType) as ICommand;
if (command == null) throw new Exception($"No instance registered for {commandType.FullName} command.");
var commandName = commandType.Name;
var commandInfo = new CommandInfo(commandName, command);
commandInfos.Add(commandInfo);
}
var bindings = new CommandBindings(commandInfos);
return bindings;
}
private static IEnumerable<Type> GetExplorerCommandTypes()
{
var assembly = typeof(ExplorerCommand).GetTypeInfo().Assembly;
foreach (Type type in assembly.GetTypes())
{
if (type.GetTypeInfo().GetCustomAttributes(typeof(ExplorerCommandAttribute), true).Count() > 0)
{
yield return type;
}
}
}
}
Commands are registered in CommandBindings
by nameof
class.
I execute them by using this syntax in code:
CommandBindings[nameof(NavigateCommand)].Execute(Model);
and by this syntax in XAML :
<ic:InvokeCommandAction Command="{Binding CommandBindings[NavigateCommand}]" />
which looks bad for me, but I can't argue it. Is there any rules that I volatile? In any case, is there anything that can improve readability of this line?
Why?
If I want to add new functionality to my control, I create command class, inherit it from ExplorerCommand
, decorate it with ExplorerCommandAttribute
and I am done. CommandBindings
are populated by retrieving all commands decorated by this attribute. I didn't change ViewModel
for that. Also UI menu items are populated from this CommandBindings
and there is no need to change UI too. This is flexibility that I achieved and won't lose it.
IExplorerModel
that I didn't show in question. \$\endgroup\$CommandBindings[nameof(NavigateCommand)].Execute(Model);
toCommandBindings[nameof(NavigateCommand)].Execute(null);
. If your question changes all the time, it will be hard to write a proper review. See also: What you may and may not do after receiving answers. \$\endgroup\$Model
to command, that isn't documented in question is more accurate than passingnull
to it ? Edit was done to simplify question and to not get confused what is thatModel
. \$\endgroup\$