在NSScrollView中检测滚动事件

时间:2013-07-13 13:43:46

标签: c# cocoa xamarin monomac

我想使用MonoMac读取和写入NSScrollView内的滚动位置(水平和垂直)。我这样做是因为我想保存并加载几个不同的状态,包括滚动位置。我没有几个不同的NSScrollViews,而是只有一个,并希望在状态发生变化时更改它。

到目前为止,我已经发现我对NSScrollView的Horizo​​ntalScroller和VerticalScroller的DoubleValue感兴趣。但我不能为我的生活弄清楚如何检测这个值何时发生变化,以便我可以保存它。无论用户是单击滚动条,拖动它还是使用鼠标或触控板,我都需要检测更改。只要滚动条移动,我想保存位置。

有什么建议吗?

2 个答案:

答案 0 :(得分:3)

我认为你正以错误的方式接近这一点。我的理解是,直接与NSScroller进行交互并不是最佳做法(我认为这不会起作用)。

请参阅此question的答案,我认为这与您的方案类似。最好的办法是设置滚动视图的原点ContentView

我将该问题的答案转换为C#:

public override void AwakeFromNib()
{
    tableView.EnclosingScrollView.ContentView.PostsBoundsChangedNotifications = true;
    NSNotificationCenter.DefaultCenter.AddObserver(this, new Selector("boundsDidChangeNotification"), 
    NSView.BoundsChangedNotification, tableView.EnclosingScrollView.ContentView);

    base.AwakeFromNib();
}

[Export("boundsDidChangeNotification")]
public void BoundsDidChangeNotification(NSObject o)
{
    var notification = o as NSNotification;
    var view = notification.Object as NSView;
    var position = view.Bounds.Location;
    Console.WriteLine("Scroll position: " + position.ToString());
} 

您可以滚动到这样的特定点:

PointF scrollTo = new PointF(19, 1571);
tableView.EnclosingScrollView.ContentView.ScrollToPoint(scrollTo);
tableView.EnclosingScrollView.ReflectScrolledClipView(tableView.EnclosingScrollView.ContentView);

你可能会觉得这很有趣:Scroll View Programming Guide for Mac

答案 1 :(得分:2)

由于Xamarin.Mac 1.12 @TheNextman发布的解决方案需要一些调整。 BoundsDidChangeNotification必须没有参数,否则将在Main中抛出System.AggregateException。如果您在选择器代码中不需要该参数,只需将其从方法签名中删除即可。但是如果你需要它,你必须使用其他版本的AddObserver方法

public override void AwakeFromNib()
{
    tableView.EnclosingScrollView.ContentView.PostsBoundsChangedNotifications = true;
    NSNotificationCenter.DefaultCenter.AddObserver(NSView.BoundsChangedNotification, BoundsDidChangeNotification, tableView.EnclosingScrollView.ContentView);

    base.AwakeFromNib();
}

public void BoundsDidChangeNotification(NSNotification notification)
{
    var view = notification.Object as NSView;
    var position = view.Bounds.Location;
    Console.WriteLine("Scroll position: " + position.ToString());
} 

请注意,action方法也可以使用lambda结构实现内联

UPDATE 在与支持者交谈之后,似乎某些组件变得更加挑剔。您仍然可以使用基于选择器的解决方案和参数,但必须在选择器名称的末尾添加分号

[Export("boundsDidChangeNotification:")]
public void BoundsDidChangeNotification(NSObject o)