Xamarin.Forms:订阅事件处理程序VS. 司令

tes*_*ing 4 c# memory-management event-handling xamarin xamarin.forms

命令主要用于在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!");
}
Run Code Online (Sandbox Code Playgroud)

VS.

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,
            }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

关于内存管理,应该取消订阅该事件.这对指挥也有效吗?在哪里订阅/取消订阅活动?在OnAppearing()OnDisappearing()

Kei*_*ome 5

通常,您的命令将作为视图模型的属性存在(在MVVM设计模式中需要).它们封装了在视图模型上执行隔离操作的概念,或者从一个视图模型转换到另一个视图模型 - 例如在导航活动期间.这会将操作与可视界面分离,从而实现对该代码的单元测试.此外,由于命令通过Bindings连接到MVM,因此您无需担心取消订阅事件.

简短形式:

  • 命令通常是ViewModel的属性,与上面代码所示的不同.
  • 它们可通过编码单元测试进行测试.
  • 它们通过Binding语法而不是事件处理程序附加到可视元素.
  • 您不需要担心取消订阅它们以进行内存管理 - 绑定不会固定与其关联的视图.

这更像是你的第二个例子应该是这样的:

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,
            }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

请注意,ViewModel类包含处理可视控件的零代码,因此可以非常容易地进行单元测试.此外,App类中处理UI的代码现在变得更加简单.

通常我会建议使用XAML标记而不是代码.在我看来,在XAML中更容易遵循Binding语法.