WPF MVVM: Отключить событие нажатия кнопки без отключения команды? - PullRequest
0 голосов
/ 29 апреля 2020

Я создаю приложение в WPF, используя MVVM, где я отображаю страницу с текстовыми полями имени файла и пути к нему. Эти текстовые поля тщательно проверяются в режиме реального времени (слишком короткий путь, слишком длинный, недопустимые символы и т. Д. c), и кнопка «Сохранить» станет активной только в том случае, если допустимы и файл, и путь. Однако я оставляю некоторые последние проверки, такие как каталог существует, файл уже существует и т. Д. c, пока пользователь не нажмет кнопку сохранения.

Проблема в том, что я немного изменяю и использую кнопку click для Navigation Service и command для сохранения или очистки в последнюю минуту во ViewModel. В этом случае команда будет обрабатываться, но после ее завершения, независимо от результата проверки, щелчок срабатывает сразу после. Итак, каким-то образом мне нужно включить или отключить только событие щелчка, пока мы не узнаем окончательный результат проверки.

Просмотр:

<TextBlock>
    Backup Name:
</TextBlock>

<TextBlock Text="{Binding Path=(Validation.Errors)/ErrorContent, 
                   ElementName=BackupFileNameTextBox}"/>

<TextBox x:Name="BackupFileNameTextBox"
         Text="{Binding BackupFileName, Mode=TwoWay, 
                UpdateSourceTrigger=PropertyChanged, 
                ValidatesOnNotifyDataErrors=True}"/>

... File Path Code same as above...

<Button Click="Pg9SaveBtnClick"
        Command="{Binding SaveBtnCommand}">
    Save
</Button>

Код позади

public Pg9BackupIntro()
{
   InitializeComponent();
}

private void Pg9SaveBtnClick(object sender, RoutedEventArgs e)
{
   // What I want to do
   if(binding.ViewModel.SaveClickEnabled) //<- Something like this
   {
       if (NavigationService.CanGoForward)
           NavigationService.GoForward();
       else
       {
           Pg10Backup page = new Pg10Backup();
           NavigationService.Navigate(page);
       }
   }
}

private void Pg9BackBtnClick(object sender, RoutedEventArgs e)
{
    NavigationService.GoBack();
}

ViewModel:

public RelayCommand SaveBtnCommand { get; private set; }

public Pg9BackupIntroViewModel()
{
   SetupBackupSave();
   SaveBtnCommand = new RelayCommand(SetBackupFileData, CanSetBackupFileData);    
}

private string _backupFileName;
public string BackupFileName
{
    get { return _backupFileName; }
    set
    {
        _backupFileName = value;
        validateFileName();
        RaisePropertyChanged();
     }
}

... BackupFilePath prop same as above...

private bool _saveClickEnabled = false;
public bool SaveClickEnabled
{
    get { return _saveClickEnabled; }
    set
    {
        _saveClickEnabled = value;
        RaisePropertyChanged();
    }
}

private bool CanSetBackupFileData(object obj)
{
    if(HasErrors)
        return false;

    return true;
}

private void SetBackupFileData(object obj)
{
    finalValidation();

    if(!HasErrors)
       SaveClickEnabled = true;
    else 
       SaveClickEnabled = false;
}

Эта самая простая вещь (показанная выше), о которой я могу подумать, - это создать свойство в виртуальной машине под названием «SaveClickEnable» "и в коде привязки к этому свойству. Затем мы можем просто проверить свойство в обработчике события click и вызвать Navigation Service, если все в порядке. К сожалению, все учебники, на которые я смотрел, связывают только обложки с помощью элементов пользовательского интерфейса, таких как текстовые поля, а не привязки к коду за переменной. Вот подход к привязке, который я пробовал:

public Pg9BackupIntro()
{
   InitializeComponent();
   Binding binding = new Binding();
   binding.Source = ViewModel or Datacontext;  //<- don't understand syntax here
   binding.Path = ViewModel.SaveClickEnabled;
}

Другая мысль состояла в том, чтобы, возможно, использовать 2 кнопки; 1 для command и 1 для click. Кнопка click никогда не будет видна, но каким-то образом вызовет щелчок на основе свойства, установленного в ВМ.

Возможно ли одно из этих действий? Я пытался сделать их обоих, но моя неловкость помешала. Я также пытался привязать к IsHitTestVisible, но это также отключает command.

<Button IsHitTestVisible="{Binding SaveClickEnabled}" //<- Disables command too
        Click="Pg9SaveBtnClick"
        Command="{Binding SaveBtnCommand}">
    Save
</Button>

Есть ли простой способ сделать это?

1 Ответ

0 голосов
/ 01 мая 2020

Я решил эту проблему, создав скрытый флажок и связав его свойство IsChecked с SaveClickEnabled. Затем я просто проверяю значение флажка в методе click, и он обходит код навигации, если есть ошибка.

Просмотр:

<CheckBox x:Name="ClickEnabledCheckbox" 
                  Visibility="Collapsed" 
                  IsChecked="{Binding SaveClickEnabled}"/> 

Code-Behind:

private void Pg9BackupBtnClick(object sender, RoutedEventArgs e)
{
    if(ClickEnabledCheckbox.IsChecked == true)
    {
        ...Navigate to next View
    }
} 

ViewModel:

private bool _saveClickEnabled = false;
public bool saveClickEnabled
{
    get { return _backupClickEnabled; }
    set
    {
        if (HasErrors)
            _backupClickEnabled = false;

         _backupClickEnabled = true;
         RaisePropertyChanged();
     }
}

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

Мой единственный wi sh был немного чище, похоже, должны быть способы убрать флажок.

...