powered by simpleCommunicator - 2.0.18     © 2024 Programmizd 02
Map
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / доступ к команде по имени из XAML
6 сообщений из 6, страница 1 из 1
доступ к команде по имени из XAML
    #40118510
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго,

что то никак не придумаю как правильно нагуглить запрос.

хочу понять по какому принципу xaml разметка находит предопределенную команду из к примеру ApplicationCommands

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

как разметка прекрасно находит комманду по строке "Open"?

и что нужно сделать что бы конструкция
<Button Command="MyCommand2" /> заработала?

то есть хотелось бы добиться эффекта что бы свои кастомные команды можно было как то зарегистрировать, что бы не обращаться к ним через привязки/статики и.т.д

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
<Window x:Class="Dialogs.ProgressDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Dialogs"
        mc:Ignorable="d"
        Title="ProgressDialog" Height="250" Width="450">
    <Grid>
         <Button Command="Open"/>
         <Button Command="{x:Static local:Dialogs.MyCommand}"/>
         <Button Command="MyCommand2" />
     </Grid>
</Window>
...
Рейтинг: 0 / 0
доступ к команде по имени из XAML
    #40118558
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff
как разметка прекрасно находит комманду по строке "Open"?

В данном случае эта "Open" соответствует команде ApplicationCommands.Open.
Как это устанавливает разметка (и почему нет ни указания пространства имён, ни имени содержащего класса):
1. Класс System.Windows.Input.ApplicationCommands находится в сборке PresentationCore. У неё в AssemblyInfo указано:
Код: c#
1.
2.
3.
[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "av")]
..
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Input")]


- этими инструкциями осуществляется маппинг пространства имен с URI=http://schemas.microsoft.com/winfx/2006/xaml/presentation на дотнетовский неймспейс System.Windows.Input (пространство имен XAML в общем случае может относиться к нескольким неймспейсам дотнета). Поскольку обычно в XAML-разметке указывается xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" (дефолтный неймспес), то для мемберов ApplicationCommands неймспейс не задается.
P.S. Я не смог повторить это, если XmlnsPrefix и XmlnsDefinition заданы в текущей сборке. В сборках из референсов это работает прекрасно.

2. Почему необязательно указывать и имя класса ApplicationCommands: при старте приложения загрузчик XAML, видя у команды строковый литерал, скармливает этот литерал классу CommandConverter из сборки PresentationFramework, чтобы определить команду, соответствующую заданной строке. И в этом конвертере просто вхардкодено:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
if (ownerType == typeof(ApplicationCommands) || ((null == knownCommand) && searchAll))
{
  switch (localName)
  {
    case "Cut":
      knownCommand = ApplicationCommands.Cut;
      break;
......


- вот и вся магия.

В общем случае для того, чтобы свою команду указать в виде строки, нужно объявить статический экземпляр RoutedCommand/RoutedUICommand в статическом классе:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
namespace TestLib
{
  public static class TestCommands
  {
    public static readonly RoutedUICommand TestCommand = new RoutedUICommand(
      "Test", "Test", typeof(TestCommands),
      new InputGestureCollection { new KeyGesture(Key.T, ModifierKeys.Control | ModifierKeys.Shift) }
    );
  }
}


тогда в разметке можно будет просто указать
Код: c#
1.
2.
<Button
  Command="tc:TestCommands.TestCommand"


Но сами по себе экземпляры RoutedCommand/RoutedUICommand никакой прикладной логики не содержат - они просто вверх по визуальному дереву пробрасывают события CanExecuted/Executed. Эти события обрабатываются при наличии обработчика у соответствующих событий CommandBinding из коллекции UIElement.CommandBindings - это подробно расписано в документации. Также существуют многочисленные сторонние реализации, где вместо событий используются ICommand - см. здесь , здесь .
...
Рейтинг: 0 / 0
доступ к команде по имени из XAML
    #40118588
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

Благодарю!

Как раз до потрохов CommandConverter я не добрался, мне как раз и было интересно как разметка умеет правильно конвертить обычную строку без указания конкретного класса.
...
Рейтинг: 0 / 0
доступ к команде по имени из XAML
    #40120442
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff
хочу понять по какому принципу xaml разметка находит предопределенную команду из к примеру ApplicationCommands

felix_ff, просто до невозможности.
В исходниках тупо сравнивается строка со всеми дефолтными командами.

Небольшой участок исходников CommandConverter с 246 строки :

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
        private static RoutedUICommand GetKnownCommand( string localName, Type ownerType )
        {
            RoutedUICommand knownCommand = null;
            bool searchAll = false;
 
            if (ownerType == null)
                searchAll = true;
 
            if (ownerType == typeof(NavigationCommands) || ((null == knownCommand) && searchAll))
            {
                switch (localName)
                {
                    case "BrowseBack":
                        knownCommand = NavigationCommands.BrowseBack;
                        break;
                    case "BrowseForward":
                        knownCommand = NavigationCommands.BrowseForward;
                        break;
                    case "BrowseHome":
                        knownCommand = NavigationCommands.BrowseHome;
                        break;
                    case "BrowseStop":
                        knownCommand = NavigationCommands.BrowseStop;
                        break;



Банальный switch-case на все допустимые значения строки.
...
Рейтинг: 0 / 0
доступ к команде по имени из XAML
    #40120605
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld Hasp,

да я уже посмотрел давно исходники :)
...
Рейтинг: 0 / 0
доступ к команде по имени из XAML
    #40120705
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff , наверное, можно что-то наколдовать в рунтайме через свой конвертер и TypeDescriptor.AddAttributes к ICommand.
Но как это сделать чтобы в режиме разработки Дизайнер XAML это принял - я не знаю.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / доступ к команде по имени из XAML
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали тему (1): Анонимы (1)
Читали форум (2): Анонимы (1), Yandex Bot 4 мин.
Пользователи онлайн (8): Анонимы (6), Yandex Bot 1 мин., Bing Bot 8 мин.
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]