Frage

I have a Exit menu item in a WPF application. When I moved the project over to utilize Caliburn Micro it has become disabled when launching the application.

<MenuItem Header="E_xit" InputGestureText="Alt+F4"
          Command="ApplicationCommands.Close"/>

Even adding IsEnabled="True" does nothing. If I remove the command Command="ApplicationCommands.Close", the menu item is enabled on startup (but obviously I want the Close command to remain attached).

My guess is there must be some kind of method or property I'm not aware of, or maybe I am not initializing the main window properly? Here is my AppBootstrapper:

public class AppBootstrapper : BootstrapperBase
{
    SimpleContainer container;

    public AppBootstrapper()
    {
        Start();
    }

    protected override void Configure()
    {
        container = new SimpleContainer();

        container.Singleton<IWindowManager, WindowManager>();
        container.Singleton<IEventAggregator, EventAggregator>();
        container.PerRequest<IShell, MainWindowViewModel>();

        var currentParser = Parser.CreateTrigger;
        Parser.CreateTrigger = (target, triggerText) => ShortcutParser.CanParse(triggerText)
            ? ShortcutParser.CreateTrigger(triggerText)
            : currentParser(target, triggerText);

    }

    protected override object GetInstance(Type service, string key)
    {
        var instance = container.GetInstance(service, key);
        if (instance != null)
            return instance;

        throw new InvalidOperationException("Could not locate any instances.");
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return container.GetAllInstances(service);
    }

    protected override void BuildUp(object instance)
    {
        container.BuildUp(instance);
    }

    protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
    {
        DisplayRootViewFor<IShell>();
    }

    protected override IEnumerable<Assembly> SelectAssemblies() {
        return new[] {
            Assembly.GetExecutingAssembly()
        };
    }
}
War es hilfreich?

Lösung

I suspect you haven't set CommandBinding for ApplicationCommands.Close.

In case CommandBinding could not be found, command will always return false from CanExecute method. So, to enable command you have to:

  • First, create CommandBinding at root element (may be at window) or at any parent element which needs to handle this command.
  • Second, provide CanExecute handler in that command binding and set e.CanExecute to True in that handler based on condition where you want to enable this menuItem.

Small sample to achieve what i said above:

<TextBox>
  <TextBox.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Close" 
                    Executed="CommandBinding_Executed" 
                    CanExecute="CommandBinding_CanExecute"/>
  </TextBox.CommandBindings>
  <TextBox.ContextMenu>
    <ContextMenu>
      <MenuItem Header="E_xit" InputGestureText="Alt+F4" 
                Command="ApplicationCommands.Close"/>
    </ContextMenu>
  </TextBox.ContextMenu>
</TextBox>

and in code behind handlers:

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{

}

private void CommandBinding_CanExecute(object sender,
                                       CanExecuteRoutedEventArgs e)
{
   e.CanExecute = true; <-- Set this to true to enable bindings.
}

You can read more about it here - How to enable a Command and Commanding Overview.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top