Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
343 / 305 / 135
Регистрация: 14.03.2015
Сообщений: 1,140
Записей в блоге: 1
1

ICommand и Template, Command Parametr

30.03.2016, 00:12. Показов 1408. Ответов 10

Author24 — интернет-сервис помощи студентам
Доброго времени суток.

У меня имеется код наподобие этого:
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ListBox 
            ItemsSource="{Binding}" 
            Style="{StaticResource lbStyle}"
            >
 
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <local:iEventControl>
                        <local:iEventControl.ContextMenu>
                            <ContextMenu>
                                <MenuItem Header="Открыть таблицу" Command="{Binding MenuItemClick}"/>
                            </ContextMenu>
                        </local:iEventControl.ContextMenu>
                    </local:iEventControl>
                </DataTemplate>
            </ListBox.ItemTemplate>
 
        </ListBox>

В свою очередь этот участок кода также является шаблоном элементов для другого объекта.

Начал свое знакомство с ICommand и хочется узнать:
Можно ли как-то в ViewModel описать MenuItemClick Command, который будет принимать ListBoxItem, у которого было вызвано контекстное меню?

Почему-то ещё данный участок кода с Command не работает - в ViewModel имеется свойство, делегат завязан на методе, но вызова не происходит, DataContext установлен. Не могли бы вы подсказать в чем проблема? (Что-то подсказывает мне, что кроме Сommand="{Binding MenuItemClick}" нужно ещё что-то писать туда.)

Спасибо.

Добавлено через 13 часов 11 минут
Может ли это быть по той причине, что при вызове Сommand="{Binding MenuItemClick}" идет вызов у родительского объекта, которым является экземпляр коллекции, которая представлена в ListBox?

Т.е. если у нас класс Student, то запрос идет к экземпляру Student, у которого запрашивается свойство MenuItemClick



Можно ли организовать код xaml так, чтобы ItemsSource бралось из родительского объекта, а Command брался из DataContext (Т.е. самого что ни на есть родительского свойства)?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.03.2016, 00:12
Ответы с готовыми решениями:

При вставке данных в таблицу: Command text was not set for the command object.
Приятного время суток. Помогите пожалуйста разобраться &lt;% Dim tmp tmp = Request('val')...

Ошибки: 1) use of class template requires template argument list 2) 'T' : undeclared identifier
Решил подправить свой класс с использованием шаблонов, но столкнулся со следующим косяком. Если я...

Template definition of non-template при использовании частичной спецификации шаблонов
Всем привет! Есть задача написать шаблон класса, принимающего в качестве параметров типа шаблон и...

'MyQueue' : use of class template requires template argument list
Написал код про шаблоны. Не могу понять почему выводит ошибку во время наследования класса. ошибки...

10
Жуткая тВарЬ
393 / 328 / 135
Регистрация: 06.02.2015
Сообщений: 962
Записей в блоге: 1
30.03.2016, 14:01 2
посмотрите тему ContextMenu для DatagridRow, включение\отключение MenuItems
1
343 / 305 / 135
Регистрация: 14.03.2015
Сообщений: 1,140
Записей в блоге: 1
30.03.2016, 20:15  [ТС] 3
amarf, Посмотрел, пробежался по проекту, который вы прикрепили.
У вас все работает, все хорошо.

Но у меня немного другая структура - У меня ужасная вложенность.
Точнее: У меня имеется TabControl, где генерятся TabItem, контент которых генерится также как ListBox (+label), и внутри ListBox происходит генерация ListBoxItem по шаблону (юзерконтрол).

Ну вот из нижней ветви мне необходимо обратится к самому верху, т.е. из своего UserControl получить исходный DataContext и оттуда стянуть мою команду.

TabControl (1) -> TabItems (1+) => ListBox (1+) ==> ListBoxItem
Т.е. имеются несколько TabItem, внутри каждого имеются несколько ListBox и внутри каждого LB имеется некоторое количество ListBoxItem
0
Жуткая тВарЬ
393 / 328 / 135
Регистрация: 06.02.2015
Сообщений: 962
Записей в блоге: 1
30.03.2016, 21:04 4
bodynar, не вижу проблем, как уже говорилось выше используйте пример и в байдинг пропишите поиск ансесора и нужный его уровень например 3, без разметки конечно всю картину не видно но как мне кажется эта проблема и выеденного яица не стоит
0
343 / 305 / 135
Регистрация: 14.03.2015
Сообщений: 1,140
Записей в блоге: 1
30.03.2016, 21:30  [ТС] 5
amarf, Если я правильно понял - в ContextMenu необходимо прописать в биндинге поиск ансесора.
Мне необходимо достучаться до DataContext окна, то в AncestorType прописать Window?

А разметка.. адова
XAML

iWeeksControl
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<TabControl ItemsSource="{Binding MyWeeks}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding WeekRange}"/>
            </DataTemplate>
        </TabControl.ItemTemplate>
 
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
                    <local:iWeekControl/>
                </ScrollViewer>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>

iWeekControl
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ItemsControl ItemsSource="{Binding}">
 
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="6"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
 
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                
                <local:iDayControl/>
                
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

iDayControl
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<StackPanel>
 
        <Label Content="{Binding Day}"/>
        
        <ListBox 
            ItemsSource="{Binding}" 
            Style="{StaticResource lbStyle}"
            >
 
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <local:iEventControl>
                            <ContextMenu>
                                <MenuItem Header="Открыть таблицу посещаемости" Command="{Binding Path=MenuItemClick}"/>
                            </ContextMenu>
                        </local:iEventControl.ContextMenu>
                    </local:iEventControl>
                </DataTemplate>
            </ListBox.ItemTemplate>
 
        </ListBox>
    </StackPanel>

iEventControl
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<Grid Margin="5">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <!-- Time Frame -->
                <RowDefinition Height="3"/>
 
                <RowDefinition Height="Auto"/>
                <!-- Type -->
                <RowDefinition Height="0"/>
 
                <RowDefinition Height="Auto"/>
                <!-- Event Name -->
                <RowDefinition Height="3"/>
 
                <RowDefinition Height="Auto"/>
                <!-- Separator -->
                <RowDefinition Height="3"/>
 
                <RowDefinition Height="Auto"/>
                <!-- Location -->
                <RowDefinition Height="3"/>
 
            </Grid.RowDefinitions>
            
            <TextBlock Grid.Row="0" Grid.Column="0"
                   Background="AliceBlue"
                   HorizontalAlignment="Left"
                   Width="Auto"
                   Text="{Binding Description}" FontSize="12"/>
 
            <TextBlock Grid.Row="0" 
                   Margin="20,0,0,0"
                   Text="{Binding TimeFrame}" FontSize="11"/>
 
            <TextBlock Grid.Row="2" 
                   Text="{Binding eType}" FontSize="10"/>
 
            <TextBlock Grid.Row="4" TextWrapping="Wrap">
            <Run Text="{Binding EventName}" />
            <Run Text="
("/><Run Text="{Binding Persons}" /><Run Text=")"/>
            </TextBlock>
 
            <Separator  Grid.Row="6"/>
 
            <TextBlock  Grid.Row="8"
                    Text="{Binding Location}" 
                    TextWrapping="Wrap"/>
        </Grid>


iWeeksControl используется в окне.

Попробовал написать что-то вроде
XML
1
<MenuItem Header="Click me 2" Command="{Binding Path=ClickMe, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=3}}" />
Выдало ошибку: Дополнительные сведения: "Инициализация "System.Windows.Data.RelativeSource" вызвала исключение.": номер строки "30" и позиция в строке "63".

Внутри ViewModel такое:
C#
1
2
3
4
 public ICommand ClickMe { get; set; }
..
 
ClickMe = new RelayCommand(x => MessageBox.Show("Called"));
0
Жуткая тВарЬ
393 / 328 / 135
Регистрация: 06.02.2015
Сообщений: 962
Записей в блоге: 1
30.03.2016, 21:55 6
bodynar, Если датаконтекст у окна то пишите ansestortype={x:type window} уровень ансестора не указывайте т.к. окно дваждый не встречается ну и мод FindAncestor..

Да главное не забыть что привязка может к Datacontext.ClickMe а не просто к ClickMe
0
343 / 305 / 135
Регистрация: 14.03.2015
Сообщений: 1,140
Записей в блоге: 1
30.03.2016, 21:59  [ТС] 7
Решил вопрос с установлением поиска родителя и использованием CommandReference
Кликните здесь для просмотра всего текста
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class CommandReference : Freezable, ICommand
    {
        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command",
            typeof(ICommand),
            typeof(CommandReference
                ),
            new PropertyMetadata(
                OnCommandChanged));
 
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }
 
        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var commandReference = d as CommandReference;
            var oldCommand = e.OldValue as ICommand;
            var newCommand = e.NewValue as ICommand;
 
            if (oldCommand != null)
            {
                oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;
            }
            if (newCommand != null)
            {
                newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;
            }
        }
 
        #region Freezable
 
        protected override Freezable CreateInstanceCore()
        {
            return this;
            throw new NotImplementedException();
        }
 
        #endregion
 
        #region ICommand Members
 
        public bool CanExecute(object parameter)
        {
            if (Command != null)
                return Command.CanExecute(parameter);
            return false;
        }
 
        public void Execute(object parameter)
        {
            Command.Execute(parameter);
        }
 
        public event EventHandler CanExecuteChanged;
 
        #endregion
    }
XML
1
<mvvm:CommandReference x:Key="ShowCommandRef" Command="{Binding ShowCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" />
XML
1
<MenuItem Header="Click me"  Command="{StaticResource ShowCommandRef}" CommandParameter="{Binding}" />
0
Жуткая тВарЬ
393 / 328 / 135
Регистрация: 06.02.2015
Сообщений: 962
Записей в блоге: 1
30.03.2016, 22:05 8
bodynar, ну можно и так вот только при использовании ресурсов можно любой объект так прикрепить, мне казалось вам нужно именно команда внутри вьюмодели
0
343 / 305 / 135
Регистрация: 14.03.2015
Сообщений: 1,140
Записей в блоге: 1
30.03.2016, 22:08  [ТС] 9
amarf, Совершенно верно, мне необходимо было перекинуть запрос из контекстного меню на команду внутри ViewModel.

Не по теме:

Если честно - наверное в силу своей криворукости не смог добиться результата способом, предложенным вами.

0
Жуткая тВарЬ
393 / 328 / 135
Регистрация: 06.02.2015
Сообщений: 962
Записей в блоге: 1
31.03.2016, 08:57 10
bodynar, так вот такая разметка не помогает?
XML
1
2
3
<ContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
     <MenuItem Header="Click me 2" Command="{Binding ClickMe}" />
</ContextMenu>
Добавлено через 57 секунд
Если не помогает, то скидывайте сам проект, потому что воспроизодить вашу модель данных не особо хочется с нуля
0
343 / 305 / 135
Регистрация: 14.03.2015
Сообщений: 1,140
Записей в блоге: 1
31.03.2016, 10:37  [ТС] 11
amarf, Привязка не работает, Output пишет:
Код
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext; DataItem=null; target element is 'ContextMenu' (Name=''); target property is 'DataContext' (type 'Object')
Да думаю не стоит пробовать искать другое решение проблемы, ведь первое найдено и оно не особо костыльное, насколько я могу понимать.

Спасибо
0
31.03.2016, 10:37
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.03.2016, 10:37
Помогаю со студенческими работами здесь

В чем различие template <typename T> от template <class T> ?
Добрый день ! Заметил в новых книгах применение записи template &lt;typename T&gt; вместо template...

Ошибка компиляции: template-id does not match any template declaration
Здравствуйте. Помогите, пожалуйста: #include &lt;iostream&gt; using namespace std; template...

Visual Studio выдаёт ошибку при вынесении объявления функции с template в .h файл. Без template всё работает
Проект содержит три файла: Source.cpp, arrTreat.h, arrTreat.cpp. Source.cpp: #include...

1>cl : Command line error D8016 : '/MTd' and '/clr' command-line options are incompatible
Не работает прога на других компах, на которых не установлена visual studio. Приложение Windows...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru