将 INotifyPropertyChanged 视图模型与 Cocoa/AppKit 绑定结合使用

Sam*_*Sam 7 c# macos cocoa cocoa-bindings xamarin.mac

我知道这很深奥,但希望有人能为我找到解决方案。

我有一个应用程序,最初是 WPF,后来迁移到 UWP,现在主要是 XF/MAUI 和 WinUI。

我想将其移植到 macOS,本质上只是替换 UI 并保留底层的 MVVM 架构,并尽可能少地编写胶水。我使用 Xamarin Mac 和 C# 来执行此操作。

Cocoa 支持绑定,但实现与标准 Microsoft MVVM 模式不兼容。

我目前的工作是做这样的事情:

public class LoginModel: NSObject
{
    private LoginViewModel _wrappedVm; // Implements both INotifyPropertyChanged and INotifyPropertyChanging

    /* Reimplement properties on LoginViewModel here and forward to the underlying view model */

    public LoginModel()
    {
        // snip: create the view model
        _wrappedVm.PropertyChanged += (s, e) =>
        {
           DidChangeValue(e.PropertyName);
        }

        _wrappedVm.PropertyChanging += (s, e) =>
        {
           WillChangeValue(e.PropertyName);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

显然这里有很多样板,但它有效。我希望有一种方法可以直接绑定到 MVVM 视图模型,而无需中间步骤,作为折衷方案,可以使用代理。我还没有研究过代理它,但根据我的理解,该模型需要是一个NSObject这样做可能会遇到挑战。

Sur*_*tap -1

不是一个大的变化,但应该减少这里的样板假设是 DidChangeValueWillChangeValue无论如何都必须在 ViewModel 中实现

public interface INSObjectBindableView
{
   void DidChangeValue(string propertyName);
   void WillChangeValue(string propertyName);
}

public static class NSObjectBindableEx
{
   public static void Bind(this INSObjectBindableView view, NSObject model)
   {
        view.PropertyChanged += (s, e) =>
        {
           DidChangeValue(e.PropertyName);
        }

        view.PropertyChanging += (s, e) =>
        {
           WillChangeValue(e.PropertyName);
        }
   }
}


Run Code Online (Sandbox Code Playgroud)

这允许您将绑定代码保留在 NSObject 子类内的一行中,例如


public class LoginModel: NSObject
{
    private LoginViewModel _wrappedVm; 

    public LoginModel()
    {
      _wrappedVm.Bind(this);
    }
}

Run Code Online (Sandbox Code Playgroud)