Xamarin.Forms:订阅事件处理程序与命令的区别

4

命令 主要用于在 ViewModel 和用户界面之间实现清晰的分离。事件订阅和 命令 有什么区别呢?考虑以下示例:

public App ()
{
    Button button = new Button
    {
        Text = "Press me",
    };

    button.Clicked += Button_Clicked;

    // The root page of your application
    MainPage = new ContentPage {
        Content = new StackLayout {
            VerticalOptions = LayoutOptions.Center,
            Children = {
                button,
            }
        }
    };
}

private void Button_Clicked(object sender, EventArgs e)
{
    System.Diagnostics.Debug.WriteLine("Pressed!");
}

对比。

public App ()
{
    Button button = new Button
    {
        Text = "Press me",
    };

    button.Command = new Command(() => System.Diagnostics.Debug.WriteLine("Pressed!"));

    // The root page of your application
    MainPage = new ContentPage {
        Content = new StackLayout {
            VerticalOptions = LayoutOptions.Center,
            Children = {
                button,
            }
        }
    };
}

关于内存管理,应该在事件中取消订阅。对于命令,这也是有效的吗?应该在哪里订阅/取消订阅事件?是在 OnAppearing()OnDisappearing() 中吗?

1个回答

6
通常,您的命令将作为视图模型的属性存在(如MVVM设计模式所要求的那样)。它们封装了在视图模型上执行孤立动作或从一个视图模型转换到另一个视图模型的概念,例如在导航活动期间。这将动作与您的可视化界面分离,从而使该代码可以进行单元测试。此外,由于命令是通过绑定在MVM中连接的,因此您不需要担心取消订阅事件。
简而言之:
- 命令通常是视图模型的属性,而不是像您上面的代码所示的那样。 - 它们可以通过编码的单元测试进行测试。 - 它们通过绑定语法而不是事件处理程序附加到可视元素。 - 您不需要担心为了内存管理而取消订阅它们 - 绑定不会固定与其关联的视图。
这更像是您第二个示例应该看起来的方式:
public class ViewModel : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged;
    private string _text;
    public string Text {
        get { return _text; }
        private set {
            if (_text != value ) {
                _text = value;
                OnPropertyChanged("Text");
            }
        }
    }
    public ICommand Cmd { get; private set; }
    public ViewModel() {
        Text = "Press me";
        Cmd = new Command(() => {
            System.Diagnostics.Debug.WriteLine("Pressed!");
            Text = "Thanks!";
        });
    }
    private void OnPropertyChanged(string propertyName) {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

//.....

public App ()
{
    Button button = new Button();
    button.BindingContext = new ViewModel();
    button.SetBinding(Button.TextProperty, "Text");
    button.SetBinding(Button.CommandProperty, "Cmd");

    // The root page of your application
    MainPage = new ContentPage {
        Content = new StackLayout {
            VerticalOptions = LayoutOptions.Center,
            Children = {
                button,
            }
        }
    };
}

请注意,ViewModel类不包含任何处理可视控件的代码,因此可以非常轻松地进行单元测试。此外,处理UI的App类中的代码现在更加简单。通常情况下,我建议使用XAML标记而不是代码。在我看来,绑定语法在XAML中更容易理解。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接