Я делаю первые шаги в использовании команд (путем реализации интерфейса ICommand
) в приложениях Windows Phone. Теперь я столкнулся с проблемой, которую я не могу понять. Я привязываю элемент управления, в этом случае это текстовое поле, к свойству CommandParameter
Button
:
<Button x:Name="BTN_Search"
Style="{StaticResource ButtonNoPressedStyle}"
BorderThickness="0"
ccontrols:TiltEffect.IsTiltEnabled="True"
Grid.Column="1"
Height="85"
Margin="0,0,0,-2"
CommandParameter="{Binding ElementName=TB_Search}"
Command="{Binding SearchTermCommand}">
<Button.Background>
<ImageBrush ImageSource="/Assets/Images/searchbtn.png" />
</Button.Background>
</Button>
Когда приложение запускается и создается модель представления, метод CanExecute
запускается дважды подряд.
public override bool CanExecute(object parameter)
{
if (parameter != null)
{
var textbox = parameter as TextBox;
if ((textbox.DataContext as MainPageViewmodel).SearchTerm == null)
{
(textbox.DataContext as MainPageViewmodel).SearchTerm = "";
return true;
}
else if (String.IsNullOrWhiteSpace(textbox.Text)) return false;
else if (textbox.Text.Any(Char.IsDigit)) return false;
else if (textbox.Text.Length < 4) return false;
else if (_commandExecuting) return false;
else
{
var bindingExpression = textbox.GetBindingExpression(TextBox.TextProperty);
bindingExpression.UpdateSource();
return true;
}
}
return true;
}
В первый раз параметр равен null
а во второй раз он содержит текстовое поле. Из-за этого поведения я должен сделать так, чтобы эти первые два раза, метод CanExecute
возвращает true, иначе кнопка будет отключена.
Я прочитал некоторые другие темы, которые могут иметь отношение к RaiseCanExecuteChanged()
, но я не уверен в этом. У этого вопроса есть некоторые ответы на эту проблему, но ответы не соответствуют моим потребностям, поскольку большинство решений для WPF (с использованием CommandManager
или IMultiValueConverter
) и другие, похоже, не работают.
Есть ли какое-либо решение, чтобы убедиться, что CanExecute
только срабатывает один раз или что объясняет это поведение?
Этот ответ не дает каких-либо определенных выводов, но после того, как я протестировал с различными привязками в CommandParameter
и посмотрел информацию, предоставленную Microsoft для интерфейса ICommand и связанного с CanExecuteChanged
события CanExecuteChanged
, я должен сделать вывод, что он имеет отношение к одному из следующего, что МакГарнагл уже предложил:
Это правдоподобно, потому что документы говорят следующее: "Происходит, когда происходят изменения, влияющие на выполнение команды или нет".
Что я заметил:
null
.CanExecute
запускается дважды при запуске. Параметр имеет значение null
в первый раз и второй раз содержит либо элемент, либо свойство указанного элемента.{Binding RelativeSource={RelativeSource Mode=Self}}
, CanExecute запускается один раз при запуске, а параметр содержит элемент Button.Как я уже говорил, это ничего не отвечает, но я думал, что предоставление дополнительной информации по этому вопросу не помешает. Если кто-то найдет окончательный ответ, объяснив, почему такое поведение, я бы, конечно, это оценил.
Во всяком случае, я использовал первый сценарий в своем приложении и реструктурировал логику, поэтому теперь он работает так, как я изначально планировал.
Я думаю, что ваше текстовое поле не инициализируется, когда параметр команды ограничен первым. Попробуйте связать текстовое поле с параметром ViewModel (параметр должен быть DependencyProperty или ваш ViewModel должен реализовывать INotifyPropertyChanged интерфейса) с режимом TwoWay затем передать этот параметр в команду параметра.