powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / ICommand.CanExecuted - параметр?
10 сообщений из 10, страница 1 из 1
ICommand.CanExecuted - параметр?
    #38522164
Всех привествую.
Есть treeview со следующим шаблоном элементов:

Код: 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.
        <HierarchicalDataTemplate DataType="{x:Type local:DatabaseFolder}" ItemsSource="{Binding Path=Childs}">
            <StackPanel Orientation="Horizontal">
                <Image Height="16">
                    <Image.Source>
                        <BitmapImage UriSource="/Icons/iconfolder.bmp" />
                    </Image.Source>
                </Image>
                <TextBlock Text="{Binding Path=itemName}">
                    <TextBlock.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header = "Добавить подкаталог" Command="{x:Static local:WireCatalog.AddNewFolderCommand}" CommandParameter="{Binding}"></MenuItem>
                            <MenuItem Header = "Добавить МЦ из Windchill" Command="{x:Static local:WireCatalog.AddNewMCItemCommand}" CommandParameter="{Binding}"></MenuItem>
                            <MenuItem Header = "Удалить" Command="{x:Static local:WireCatalog.RemoveFolderCommand}"  CommandParameter="{Binding}"/>
                        </ContextMenu>
                    </TextBlock.ContextMenu>
                </TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type local:DatabaseMCItem}">
            <StackPanel Orientation="Horizontal">
                <Image Height="16">
                    <Image.Source>
                        <BitmapImage UriSource="/Icons/iconfile.bmp" />
                    </Image.Source>
                </Image>
                <TextBlock Text="{Binding Path=itemName}" />
            </StackPanel>
        </HierarchicalDataTemplate>



Команда удаления каталога (Command="{x:Static local:WireCatalog.RemoveFolderCommand}") должна работать лишь тогда, когда каталог пустой. соотвественно хочу проверить это в CanExecuted, написал примитивную проверку:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
        public class RemoveFolderFromWireKatalog : ICommand
        {

            public bool CanExecute(object parameter)
            {
                return (parameter is DatabaseFolder) && (((DatabaseFolder)parameter).Childs.Count == 0);
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                throw new NotImplementedException();
            }
        }


но на входе у CanExecute постоянно null. Что я делаю не так?
и сразу второй вопрос - заметил, что wpf дёргает CanExecute в момент отрисовки элемента в дереве, а не в момент отображения контекстного меню, это нормальное поведение? Переползаю на впф с винформс, пока всё как-то в новинку)
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38522421
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неделя_на_wpf,

ну в момент отрисовки да null. А когда команду вызовите придет ваш item.
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38522657
netivan,
в Execute()-то итем придёт, но вот только поскольку в CanExecute() при отображении менюшки пришёл null -> CanExecute возвращает false -> пункт меню не активен -> до вызова дело не дойдёт вовсе)
Сама команда работала до тех пор, пока не убрал безвариантное return true в CanExecute() :)
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38522765
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неделя_на_wpf,

проверьте DataContext у MenuItem'ов - он часто слетает, особенно в случае элементов, сгенерированных через DataTemplate: https://www.google.ru/search?q=wpf contextmenu datacontext is null
Может помочь привязка датаконтекста самого ContextMenu через DataContext PlacementTarget'а. Или можно использовать DataContextSpy .
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38523695
maratoss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неделя_на_wpf,

Команда сама должна уведомлять о своем состоянии интерфейсу через событие CanExecuteChanged,
ну или предоставлять возможность стороннему объекту вызвать это событие,
если этому объекту виднее, когда стоит нажимать на кнопку пользователю, а когда нет

После того как событие CanExecuteChanged сработает,
все подписчики вызовут CanExecute у команды и обновят UI в зависимости, от того что этот метод вернет.

поэтому можно сделать следующее:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
<ContextMenu>
	<MenuItem Header = "Добавить подкаталог" Command="{x:Static local:WireCatalog.AddNewFolderCommand}" CommandParameter="{Binding}"></MenuItem>
	<MenuItem Header = "Добавить МЦ из Windchill" Command="{x:Static local:WireCatalog.AddNewMCItemCommand}" CommandParameter="{Binding}"></MenuItem>
	<MenuItem Header = "Удалить">
		<MenuItem.Command>
			<!-- 
				только тут есть одна проблема, биндить можно только к DependencyProperty
				поэтому тут нужно прибиндить либо через AttachProperty, либо через Behavior либо MarkupExtension
				
				ну или самое простое, команда должна отнаследовать класс DependencyObject
				и свойство DatabaseFolder - переделать в DependencyProperty
			-->
			<local:WireCatalog.RemoveFolderCommand DatabaseFolder="{Binding}" />
		</MenuItem.Command>
	</MenuItem>
</ContextMenu>



Код: 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.
public class RemoveFolderFromWireKatalog : ICommand
{
	private DatabaseFolder _databaseFolder;
	public DatabaseFolder DatabaseFolder
	{ 
		get { return _databaseFolder; }
		set { _databaseFolder = value; OnDatabaseFolderChanged(); }
	}
	
	public bool CanExecute(object parameter)
	{
		return !DatabaseFolder.Childs.Any();
	}

	public event EventHandler CanExecuteChanged;

	public void Execute(object parameter)
	{
		throw new NotImplementedException();
	}
	
	private void OnDatabaseFolderChanged()
	{
		DatabaseFolder.CollectionChanged += (s, e) => CanExecuteChanged(this, EventArgs.Empty);
	}
}
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38524294
maratoss,

спасибо за помощь, но теперь получил null вообще везде)

Код: xml
1.
2.
3.
4.
5.
<MenuItem Header = "Удалить">
                                <MenuItem.Command>
                                    <local:RemoveFolderFromWireKatalog DbFolder="{Binding}" />
                                </MenuItem.Command>
                            </MenuItem>



Код: 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.
        public class RemoveFolderFromWireKatalog : DependencyObject, ICommand
        {

            public static readonly DependencyProperty DbFolderProperty = DependencyProperty.Register("DbFolder", typeof(DatabaseFolder), typeof(RemoveFolderFromWireKatalog));

            public DatabaseFolder DbFolder
            {
                set { SetValue(DbFolderProperty, value); OnDatabaseFolderChanged(); }
                get { return (DatabaseFolder)GetValue(DbFolderProperty); }
            }


            public bool CanExecute(object parameter)
            {
                //return !DatabaseFolder.Childs.Any();
                return true;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                //throw new NotImplementedException();
                MessageBox.Show(DbFolder.GetType().ToString()); // <----------- падаем (nullvalue)    
            }

            private void OnDatabaseFolderChanged()
            {
                DbFolder.Childs.CollectionChanged += (s, e) => CanExecuteChanged(this, EventArgs.Empty);
            }

        }
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38524576
maratoss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
неделя_на_wpf,

Оказывается что меню находится за пределами визуального дерева
ну и как писал Сон Веры Павловны установи DataContext через PlacementTarget

Код: xml
1.
2.
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, 
	RelativeSource={RelativeSource Self}}" >



http://www.codeproject.com/Articles/162784/WPF-ContextMenu-Strikes-Again-DataContext-Not-Upda
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38524645
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratoss,

интересно. Хотя обойти это можно используя нормальный MVVM и иметь SelectedItem в модели.
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38524704
maratoss,

DataContext в ContextMenu пробовал сразу устанавливать, но проблема вроде бы не в этом, ибо я опять вернулся к тому же самому. Ради интереса попробовал:
Код: xml
1.
2.
3.
4.
5.
<MenuItem Header="Удалить" CommandParameter="{Binding}">
<MenuItem.Command>
<local:RemoveFolderFromWireCatalog DbFolder="{Binding}" />
</MenuItem.Command>
</MenuItem> 



в итоге в icommand.Execute получаю - parameter=DatabaseFolder (то есть привязка работает), а свойство команды DbFolder = null
Пока ковыряюсь с другим, решения так и не придумал
...
Рейтинг: 0 / 0
ICommand.CanExecuted - параметр?
    #38526913
Взлетело с RoutedCommand - в CanExecute e.Parameter честно установлен. Спасибо тем, кто помогал.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / ICommand.CanExecuted - параметр?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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