Xamarin Mac KVO 模型绑定 - 更改触发两次
Xamarin Mac KVO model bindings - change fires twice
我正在尝试在 Xamarin Mac 桌面应用程序中实现 KVO 绑定。
我已按照文档进行操作,它正在运行,但绑定似乎每次都会触发 2 个更改事件!
如果我用这样的绑定创建一个 KVO 模型...
private int _MyVal;
[Export("MyVal")]
public int MyVal
{
get { return _MyVal; }
set
{
WillChangeValue("MyVal");
this._MyVal = value;
DidChangeValue("MyVal");
}
}
并在 bindings
部分下的 Xcode 中绑定一个控件到路径 self.SettingsModel.MyValue
看起来一切正常,控件显示模型值,更改模型值以编程方式更新控件,更改控件更新模型值。
但是,它运行了两次更改事件。
我正在监听变化,因此我可以用值点击 API。
SettingsModel.AddObserver(this, (NSString)key, NSKeyValueObservingOptions.New, this.Handle);
然后……
public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
{
switch (keyPath)
{
case "MyValue":
// CODE HERE THAT UPDATES AN API WITH THE VALUE
// But this handler fires twice.
break;
}
}
我不确定是 Xamarin 还是 XCode 导致了双重触发。
有趣的是,如果您没有指定 Xcode WillChangeValue
和 DidChangeValue
方法,那么它不会触发两次 - 就好像 Xamarin 已经自动触发了一次更改。但是,当以编程方式更新模型值时,它不再触发更改...
[Export("MyVal")]
public int MyVal { get; set }
以上内容适用于 Xcode 控件,它们将更新模型并触发更改事件。
但以编程方式更新它
this.SettingsModel.MyVal = 1;
不触发更改事件。
关于如何停止触发 2 个更改事件的任何想法都非常令人困惑,因为我不想每次都点击 API 两次!
当它触发两次时,第一次的堆栈跟踪(删节)有...
MainViewController.ObserveValue
ObjCRuntime.Messaging.void_objc_msgSendSuper_IntPtr()
Foundation.NSObject.DidChangeValue(string forKey)
CameraSettingsModel.set_MyValue(int value)
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
看起来不错,但是第二个...
MainViewController.ObserveValue
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
没有提到触发事件的设置模型
你正在打这个 - Receiving 2 KVO notifications for a single KVC change
并且需要覆盖它出现的 AutomaticallyNotifiesObserversForKey。
Cocoa 是 "doing you a favor" 通过为您发送通知,这很棒,除非您有托管版本也发送通知。
看起来像这样:
[Export ("automaticallyNotifiesObserversForKey:")]
public static new bool AutomaticallyNotifiesObserversForKey (string key) => false;
bool _checkValue;
[Export("CheckValue")]
public bool CheckValue
{
get { return _checkValue; }
set
{
WillChangeValue("CheckValue");
_checkValue = value;
DidChangeValue("CheckValue");
}
}
public override void ViewDidLoad ()
{
base.ViewDidLoad();
this.AddObserver("CheckValue", NSKeyValueObservingOptions.New, o =>
{
Console.WriteLine($"Observer triggered for {o}");
});
CheckValue = false;
}
我正在尝试在 Xamarin Mac 桌面应用程序中实现 KVO 绑定。 我已按照文档进行操作,它正在运行,但绑定似乎每次都会触发 2 个更改事件!
如果我用这样的绑定创建一个 KVO 模型...
private int _MyVal;
[Export("MyVal")]
public int MyVal
{
get { return _MyVal; }
set
{
WillChangeValue("MyVal");
this._MyVal = value;
DidChangeValue("MyVal");
}
}
并在 bindings
部分下的 Xcode 中绑定一个控件到路径 self.SettingsModel.MyValue
看起来一切正常,控件显示模型值,更改模型值以编程方式更新控件,更改控件更新模型值。
但是,它运行了两次更改事件。
我正在监听变化,因此我可以用值点击 API。
SettingsModel.AddObserver(this, (NSString)key, NSKeyValueObservingOptions.New, this.Handle);
然后……
public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
{
switch (keyPath)
{
case "MyValue":
// CODE HERE THAT UPDATES AN API WITH THE VALUE
// But this handler fires twice.
break;
}
}
我不确定是 Xamarin 还是 XCode 导致了双重触发。
有趣的是,如果您没有指定 Xcode WillChangeValue
和 DidChangeValue
方法,那么它不会触发两次 - 就好像 Xamarin 已经自动触发了一次更改。但是,当以编程方式更新模型值时,它不再触发更改...
[Export("MyVal")]
public int MyVal { get; set }
以上内容适用于 Xcode 控件,它们将更新模型并触发更改事件。
但以编程方式更新它
this.SettingsModel.MyVal = 1;
不触发更改事件。
关于如何停止触发 2 个更改事件的任何想法都非常令人困惑,因为我不想每次都点击 API 两次!
当它触发两次时,第一次的堆栈跟踪(删节)有...
MainViewController.ObserveValue
ObjCRuntime.Messaging.void_objc_msgSendSuper_IntPtr()
Foundation.NSObject.DidChangeValue(string forKey)
CameraSettingsModel.set_MyValue(int value)
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
看起来不错,但是第二个...
MainViewController.ObserveValue
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
没有提到触发事件的设置模型
你正在打这个 - Receiving 2 KVO notifications for a single KVC change
并且需要覆盖它出现的 AutomaticallyNotifiesObserversForKey。
Cocoa 是 "doing you a favor" 通过为您发送通知,这很棒,除非您有托管版本也发送通知。
看起来像这样:
[Export ("automaticallyNotifiesObserversForKey:")]
public static new bool AutomaticallyNotifiesObserversForKey (string key) => false;
bool _checkValue;
[Export("CheckValue")]
public bool CheckValue
{
get { return _checkValue; }
set
{
WillChangeValue("CheckValue");
_checkValue = value;
DidChangeValue("CheckValue");
}
}
public override void ViewDidLoad ()
{
base.ViewDidLoad();
this.AddObserver("CheckValue", NSKeyValueObservingOptions.New, o =>
{
Console.WriteLine($"Observer triggered for {o}");
});
CheckValue = false;
}