NSTableView:浮动(或固定)列

时间:2015-11-18 11:56:21

标签: cocoa nstableview floating nstablecolumn

我想要达到的目标是这样的:
DevExpress Grid
Table with fixed columns

上述链接中的表格可以包含“固定”列,不会与其他内容一起滚动。

我知道NSTableView的{​​{1}}功能和floatsGroupRows的{​​{1}}方法;但要实现上述目标,这还不够:

  • 列不是NSScrollView s,首先是
  • 表格标题和表格内容放在addFloatingSubview:forAxis:下的2个单独的NSView中(这是NSClipView的默认操作)

所以很久以来我找不到任何内置的解决方案。我唯一的想法是彼此相邻使用3 NSScrollView s(左侧+1,右侧+1);并手动同步它们中的垂直滚动。如何同步水平滚动,现在这是一个更难的问题。左侧和右侧不应滚动,因此应“浮动”。 对于表格的内容,NSTableView的{​​{1}}方法应该适用于IMO (*);但是列标题是不同的动物。好吧,仍然应该有办法通过黑客绘制列来实现这种浮动行为......

但是,我还没有开始实现上面的那个,因为我的NSTableView已经足够缓慢(NSTableview View Based Scrolling Performance)了,而且我确信这些加上的东西会让它慢下来。 / p>

有没有人(更好)知道如何在Cocoa中实现浮动列? 任何帮助非常感谢!

修改

(*):NSScrollView的{​​{1}}不起作用。正如我现在所看到的,如果给予此方法的addFloatingSubview:forAxis:NSTableView的子视图,则会得到特殊处理。该表可能会添加自己的逻辑;现在对我来说,NSScrollView一次只能有一个浮动行。

1 个答案:

答案 0 :(得分:1)

我已经实现了垂直同步两个NSTableViews。不清楚为什么你需要三个,但无论如何。请注意,这是使用Xamarin.Mac lib的所有c#代码。这些是本机Cocoa平台上的包装器。您必须自己将此转换为obj c / swift。这应该不难。

从笔尖醒来:

table1.EnclosingScrollView.ContentView.PostsBoundsChangedNotifications = true;
NSNotificationCenter.DefaultCenter.AddObserver (NSView.BoundsChangedNotification, BoundsDidChangeNotification, table1.EnclosingScrollView.ContentView);
table2.EnclosingScrollView.ContentView.PostsBoundsChangedNotifications = true;
NSNotificationCenter.DefaultCenter.AddObserver (NSView.BoundsChangedNotification, BoundsDidChangeNotification, table2.EnclosingScrollView.ContentView);

因此,每当其中一个表滚动时,就会调用BoundsDidChangeNotification,并负责同步y轴。请注意,即使由于惯性滚动或边界的程序更改(或放大/缩小或调整视图大小等)而发生滚动时,此功能仍然有效。此类事件可能并不总是触发专门用于“用户滚动”的事件,因此,这是更好的方法。 Bellow是BoundsDidChangeNotification方法:

public void BoundsDidChangeNotification (NSNotification o)
    {
        if (o.Object == table1.EnclosingScrollView.ContentView) {
            var bounds = new CGRect (new CGPoint (table2.EnclosingScrollView.ContentView.Bounds.Left, table1.EnclosingScrollView.ContentView.Bounds.Top), table2.EnclosingScrollView.ContentView.Bounds.Size);
            if (bounds == table2.EnclosingScrollView.ContentView.Bounds)
                return;
            table2.ScrollPoint (bounds.Location);
        } else {
            var bounds = new CGRect (new CGPoint(table1.EnclosingScrollView.ContentView.Bounds.Left, table2.EnclosingScrollView.ContentView.Bounds.Top), table1.EnclosingScrollView.ContentView.Bounds.Size);
            if (table1.EnclosingScrollView.ContentView.Bounds == bounds)
                return;
            table1.ScrollPoint (bounds.Location);
        }
    }

这里没什么太花哨的......有一些边界相等检查以避免最终的无限循环(table1告诉table2同步然后table2 tels table1等等,永远)。 AFAI记得,如果你ScrollPoint到当前的滚动位置,边界确实没有被触发,但是因为否则会发生无限循环,我认为额外的检查是值得的 - 你永远不会知道未来的os x版本会发生什么。 / p>