Обработчик событий XAML в некорневом объекте

#xaml #uwp-xaml

#xaml #uwp-xaml

Вопрос:

Представьте следующий XAML:

 <Page
    x:Class="MyProject.MainPage"
    xmlns:local="using:MyProject">

   <local:MyStackPanel>
       <Button Content="Go" Click="OnGo"/>
   </local:MyStackPanel>
</Page>
  

XAML предполагает, что OnGo это метод в классе page. Могу ли я как-то декларативно указать, что OnGo находится в MyStackPanel вместо этого?

Я знаю, что могу назначить обработчик событий программно после загрузки страницы. Мне интересно, возможно ли это чисто средствами XAML. «Нет» — приемлемый ответ 🙂

Ответ №1:

По вашему требованию вы могли бы связать MyStackPanel DataContext с самим собой. Затем создайте BtnClickCommand тот, который использовался для привязки команды button в MyStackPanel классе, как показано ниже.

 public class MyStackPanel : StackPanel
{
    public MyStackPanel()
    {

    }

    public ICommand BtnClickCommand
    {
        get
        {
            return new RelayCommand(() =>
            {


            });
        }
    }

}
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;
    /// <summary>
    /// Raised when RaiseCanExecuteChanged is called.
    /// </summary>
    public event EventHandler CanExecuteChanged;
    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action execute)
        : this(execute, null)
    {
    }
    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }
    /// <summary>
    /// Determines whether this RelayCommand can execute in its current state.
    /// </summary>
    /// <param name="parameter">
    /// Data used by the command. If the command does not require data to be passed,
    /// this object can be set to null.
    /// </param>
    /// <returns>true if this command can be executed; otherwise, false.</returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }
    /// <summary>
    /// Executes the RelayCommand on the current command target.
    /// </summary>
    /// <param name="parameter">
    /// Data used by the command. If the command does not require data to be passed,
    /// this object can be set to null.
    /// </param>
    public void Execute(object parameter)
    {
        _execute();
    }
    /// <summary>
    /// Method used to raise the CanExecuteChanged event
    /// to indicate that the return value of the CanExecute
    /// method has changed.
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        var handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}
  

Использование

 <local:MyStackPanel DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
    <Button Command="{Binding BtnClickCommand}" Content="ClickMe" />
</local:MyStackPanel>
  

Комментарии:

1. Спасибо. Хотя вряд ли декларативный.

2. @SevaAlekseyev Этот ответ не соответствует требованиям?

3. Нет никаких требований, просто надеюсь, что XAML был более гибким, чем я знал 🙂 По-видимому, нет.

4. @SevaAlekseyev, Ладно, Xaml был негибким. он не может делать то, что вы хотите. Вы можете размещать сообщения на пользовательском голосе .