Столкнулся с проблемой.
Имеется внутри View
И внутри ViewModel такое
public RelayCommand ShowCommand { get; set; }
void InitCommands()
{
ShowCommand = new RelayCommand(
x => Show(x),
(can) =>
{
return can == null ? false :
Directory.Exists(ApplicationPath.Groups + (can as Event).Persons + @"/") ?
File.Exists(ApplicationPath.Groups + (can as Event).Persons + @"/" + "GroupList.dat")
: false;
});
}
В (can) все время (при запуске страницы) заходит null. Когда же я выбираю в ListBox элементо и жмакаю правой кнопкой, то меню айтем с данной командой не доступен.
Директория и файл существуют.
Event - мой класс, в котором есть поле строковое Persons;
Команду видит, биндинг работает.
Также прикрепляю класс RelayCommand - paste.org.ru/?wu3n62
Ответ
Проблема вот в чём.
У вас дана реализация CanExecute, но нет реализации CanExecuteChanged. Поэтому изменения CanExecute не подхватываются.
Есть несколько путей решения этой проблемы.
Во-первых, ваша реализация RelayCommand (это нестандартный класс, значит, вы берёте его из какого-то фреймворка или написали самостоятельно) может предоставлять возможность запустить CanExecuteChanged. Тогда вы должны сами реализовать логику, которая определяет эти обстоятельства, и «дёргает» CanExecuteChanged в нужный момент. Этот путь может быть сложен, если ваш параметр меняется со временем.
Во-вторых, вы можете в тот момент, когда по логике программы команда может активироваться или деактивироваться, вызвать вручную CommandManager.InvalidateRequerySuggested. После этого значение CanExecute будет перечитано.
У меня и правда InvalidateRequerySuggested не сработало на RelayCommand. Я поменял его на RoutedUICommand, и всё взлетело.
Смотрите. Во-первых, определяем нужную команду:
public class GlobalCommands : RoutedUICommand
{
private GlobalCommands() { } // запрещаем создавать экземпляры снаружи
public static GlobalCommands ShowStudents =
new GlobalCommands() { Text = "Отобразить список студентов" };
// сюда можно добавлять ещё команды
}
Затем, в главной VM создаём CommandBinding
public IEnumerable
void InitCommands()
{
supportedBindings = new List
// загрузить конкретную группу
}
}
bool CanShowStudents(object iEvent)
{
Debug.WriteLine("CanShowStudents called");
var ev = iEvent as Event;
if (ev == null)
return false;
Debug.WriteLine($"CanShowStudents, persons = {ev.Persons}");
return Directory.Exists(AppPathGroups + @"\" + ev.Persons) &&
File.Exists(AppPathGroups + @"\" + ev.Persons + @"\" + "GroupList.dat");
}
Таким образом создаётся привязка команды к её реализации.
Затем, привязки нужно зарегистрировать, чтобы какой-нибудь UI-объект их обрабатывал. Например, окно. Для этого в App.xaml.cs пишем:
// вызывается на Application.Startup
void ApplicationStartup(object sender, StartupEventArgs e)
{
var vm = new ViewModel();
foreach (var binding in vm.SupportedBindings)
CommandManager.RegisterClassCommandBinding(typeof(Window), binding);
var w = new Window1();
w.DataContext = vm;
w.ShowDialog();
}
И наконец, в UI пишем такое:
В таком варианте код работает.
Комментариев нет:
Отправить комментарий