@Endrju - пожалуйста, посмотрите на даты и отредактируйте историю, прежде чем комментировать

нтересован в создании команд, которые доступны из любого места в моем приложении WPF.

Я бы хотел, чтобы они работали так же, какCut, Copy, Paste и другие команды прикладного уровня, а именно:

<Button Command="Paste" />

Я предполагал, что могу установить CommandBindings для экземпляра приложения, но это свойство недоступно.

Как это сделать?

Лучшее, что мне удалось сделать, - это создать набор команд в окне верхнего уровня и затем обращаться к ним следующим образом ...:

<Button Command="{x:Static namespace::MainWindow.CommandName}" />

Который работает, но, конечно, тесно связан, и поэтому очень хрупкий.

Ответы на вопрос(5)

Решение Вопроса

ия WPF и реализовать обработчики команд в классе Application.

Прежде всего, создайте статический командный контейнерный класс. Например,

namespace WpfApplication1 
{
    public static class MyCommands
    {
        private static readonly RoutedUICommand doSomethingCommand = new RoutedUICommand("description", "DoSomethingCommand", typeof(MyCommands));

        public static RoutedUICommand DoSomethingCommand
        {
            get
            {
                return doSomethingCommand;
            }
        }
    }
}

Затем установите вашу пользовательскую команду на Button.Command, как это.

<Window x:Class="WpfApplication1.MainWindow"
        ...
        xmlns:local="clr-namespace:WpfApplication1">
    <Grid>
        ...
        <Button Command="local:MyCommands.DoSomethingCommand">Execute</Button>
    </Grid>
</Window>

Наконец, реализуйте обработчик команды вашей пользовательской команды в классе Application.

namespace WpfApplication1 
{

    public partial class App : Application
    {
        public App()
        {
            var binding = new CommandBinding(MyCommands.DoSomethingCommand, DoSomething, CanDoSomething);

            // Register CommandBinding for all windows.
            CommandManager.RegisterClassCommandBinding(typeof(Window), binding);
        }

        private void DoSomething(object sender, ExecutedRoutedEventArgs e)
        {
            ...
        }

        private void CanDoSomething(object sender, CanExecuteRoutedEventArgs e)
        {
            ...
            e.CanExecute = true;
        }
    }
}
 ocodo17 янв. 2011 г., 06:40
Спасибо, Шоу, я попробую. Я предполагаю, что могу использовать новые имена команд, напримерApplicationCommands.MyCommand? Если нет, то это не ответит на мой вопрос.
 ocodo18 янв. 2011 г., 02:13
Спасибо, это здорово, и это решает проблему жесткой связи, которая была самой важной для меня.
 Shou Takenaka17 янв. 2011 г., 13:27
Я изменил пример кода. Вам не нужно добавлять новые команды в класс ApplicationCommands, потому что если вы создаете статический класс контейнера команд, он может использоваться точно так же, как класс ApplicationCommands.
 ocodo17 янв. 2011 г., 09:27
Пожалуйста, измените пример, чтобы использовать пользовательскую команду, а не Вставить. Я не могу найти другую ссылку для добавления новых команд вApplicationCommandsМожете ли вы предоставить ссылку? - Кроме того, вы бы показали использование XAML, особенно если оно отличается от<Button Command="MyCommand" /> - благодарю вас.
 Shou Takenaka17 янв. 2011 г., 06:53
Вы также можете использовать пользовательские команды.

но после нескольких часов исследований я обнаружил, что это действительно просто.

Сначала настройте свою команду, как обычно, но добавьте статическое свойство для WPF, чтобы он мог получить экземпляр вашей команды.

class MyCommand : ICommand
{
    // Singleton for the simple cases, may be replaced with your own factory     
    public static ICommand Instance { get; } = new MyCommand();

    public bool CanExecute(object parameter)
    {
        return true; // TODO: Implement
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        // TODO: Implement       
    }   
}

Добавьте ссылку на пространство имен вашей команды в XAML (последняя строка), например так:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:commands="clr-namespace:MyProject.Commands">     

Затем просто укажите ссылку на ваше статическое свойство в вашем XAML следующим образом:

<Button Content="Button" Command="commands:MyCommand.Instance" />

ОбъявитьCommandBinding вApplication уровень, с которого он может быть использован везде.

<Application.Resources>       
    <CommandBinding x:Key="PasteCommandKey" Command="ApplicationCommands.Paste" CanExecute="CommandBinding_CanExecute_1"/>
</Application.Resources>

В вашейApp.xaml.cs файл, определите соответствующие обработчики:

  private void CommandBinding_CanExecute_11(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
    {
      e.CanExecute = false;
    }

использование

В любом файле xaml используйте его, как показано ниже:

 <RichTextBox x:Name="Rtb1" ContextMenuOpening="Rtb1_ContextMenuOpening_1" FontSize="15" Margin="10,10,10,-73">            
        <RichTextBox.CommandBindings>
            <StaticResourceExtension ResourceKey="PasteCommandKey"/>
        </RichTextBox.CommandBindings>
 ocodo27 сент. 2017 г., 08:56
@Endrju - пожалуйста, посмотрите на даты и отредактируйте историю, прежде чем комментировать
 Endrju26 сент. 2017 г., 00:43
Этот очень конкретный ответ мне очень помог. Никто другой не сказал, что можно поставить<CommandBinding> внутри<Application.Resources>, @ocodo Ваш комментарий недействителен.
 ocodo15 окт. 2016 г., 11:05
Приведенные объяснения и качество ответов уже размещены. Ваш ответ на самом деле не добавляет ценности. Пожалуйста, не размещайте код без объяснения причин. Я рекомендую отредактировать ваш ответ, чтобы сначала объяснить, а затем показать код. Спасибо.

что я решил сейчас внести свой вклад и поделиться ;-)

Основываясь на ответе Шоу Такенака, вот моя реализация.

Мой интерес был производить толькоодин многоразовый файл.

Сначала создайте команду (ы) класса контейнера

namespace Helpers
{
    public class SpecificHelper
    {
        private static RoutedUICommand _myCommand = new RoutedUICommand("myCmd","myCmd", typeof(SpecificHelper));
        public static RoutedUICommand MyCommand { get { return _myCommand; } }

        static SpecificHelper()
        {
            // Register CommandBinding for all windows.
            CommandManager.RegisterClassCommandBinding(typeof(Window), new CommandBinding(MyCommand, MyCommand_Executed, MyCommand_CanExecute));
        }

        // TODO: replace UIElement type by type of parameter's binded object
        #region MyCommand
        internal static void MyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (!verifType<UIElement>(e.Parameter)) return;

            e.Handled = true;
            // TODO : complete the execution code ...
        }

        internal static void SelectAll_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (!verifType<UIElement>(e.Parameter)) return;

            e.CanExecute = true;
            var item = (e.Parameter as UIElement);
            // TODO : complete the execution code ...
        }
        #endregion

        private static bool verifType<T>(object o)
        {
            if (o == null) return false;
            if (!o.GetType().Equals(typeof(T))) return false;
            return true;
        }
    }
}

Затем объявите ресурс в App.xaml:

<Application x:Class="Helper.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:h="clr-namespace:Helpers"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" 
             StartupUri="MainWindow.xaml" >
    <Application.Resources>
        <h:SpecificHelper x:Key="sh" />
    </Application.Resources>
</Application>

Наконец, свяжите любое свойство команды со свойством ресурса приложения:

<Button Content="Click to execute my command"
        Command="{Binding Source={StaticResource sh}, Path=MyCommand}"
        CommandParameter="{Binding ElementName=myElement}" />

вот и все, ребята :-)

Если вы попытаетесь определитьCommandBindings или жеInputBindings как ресурсы в вашемApp.xamlвы обнаружите, что не можете их использовать, потому что XAML не позволяет вам использовать также:

<Window ... CommandBindings="{StaticResource commandBindings}">

или установить привязки команд с помощью установщика стиля:

<Setter Property="CommandBindings" Value="{StaticResource commandBindings}">

потому что ни одно из этих свойств не имеет метода доступа set. Используя идею вэта почтаЯ придумал чистый способ использования ресурсов изApp.xaml или любой другой словарь ресурсов.

Сначала вы определяете привязки команд и ввода косвенно, как и любой другой ресурс:

    <InputBindingCollection x:Key="inputBindings">
        <KeyBinding Command="Help" Key="H" Modifiers="Ctrl"/>
    </InputBindingCollection>
    <CommandBindingCollection x:Key="commandBindings">
        <CommandBinding Command="Help" Executed="CommandBinding_Executed"/>
    </CommandBindingCollection>

и затем вы ссылаетесь на них из XAML другого класса:

<Window ...>
    <i:Interaction.Behaviors>
        <local:CollectionSetterBehavior Property="InputBindings" Value="{StaticResource inputBindings}"/>
        <local:CollectionSetterBehavior Property="CommandBindings" Value="{StaticResource commandBindings}"/>
    </i:Interaction.Behaviors>
    ...
</Window>

CollectionSetterBehavior это повторно используемое поведение, которое не «устанавливает» свойство в его значение, а вместо этого очищает коллекцию и повторно заполняет ее. Таким образом, коллекция не меняется, только ее содержимое.

Вот источник для поведения:

public class CollectionSetterBehavior : Behavior<FrameworkElement>
{
    public string Property
    {
        get { return (string)GetValue(PropertyProperty); }
        set { SetValue(PropertyProperty, value); }
    }

    public static readonly DependencyProperty PropertyProperty =
        DependencyProperty.Register("Property", typeof(string), typeof(CollectionSetterBehavior), new UIPropertyMetadata(null));

    public IList Value
    {
        get { return (IList)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(IList), typeof(CollectionSetterBehavior), new UIPropertyMetadata(null));

    protected override void OnAttached()
    {
        var propertyInfo = AssociatedObject.GetType().GetProperty(Property);
        var property = propertyInfo.GetGetMethod().Invoke(AssociatedObject, null) as IList;
        property.Clear();
        foreach (var item in Value) property.Add(item);
    }
}

Если вы не знакомы с поведением, сначала добавьте это пространство имен:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

и добавьте соответствующую ссылку на ваш проект.

 ocodo17 янв. 2011 г., 09:25
Пожалуйста, покажите, как бы вы затем использовали эти команды в XAML, например,<Button Command="MyCustomCommand"/>

Ваш ответ на вопрос