【问题标题】:Implementing NSOutlineViewDataSource using MonoMac使用 MonoMac 实现 NSOutlineViewDataSource
【发布时间】:2012-01-22 11:12:32
【问题描述】:

我正在尝试为NSOutlineView 实现数据源。问题是我不知道从outlineView:child:ofItem:返回什么类型的对象。

当前代码如下所示:

[Export("outlineView:child:ofItem:")]
public NSObject childOfItem(NSOutlineView outline, int child, NSObject item)
{
    return new MyItem();
}

使用 MyItem:

public class MyItem : NSObject
{}

编辑:使用此代码,我在返回 MyItem 后得到一个 InvalidCastException

【问题讨论】:

    标签: c# cocoa mono nstableview monomac


    【解决方案1】:

    如果您从 NSOutlineViewDataSource 继承新类型,那么您不应该在您自己的方法上重新导出它的 outlineView:child:ofItem: 选择器。相反,您应该做的是覆盖已经导出此选择器的 GetChild 方法,例如

    public overrride NSObject GetChild (NSOutlineView outlineView, int childIndex, NSObject ofItem)
    {
        return new MyItem ();
    }
    

    注意:这可能无济于事,因为我没有尝试过(我主要做 MonoTouch 的事情),但请检查您可能在应用程序中重新定义/导出的其他选择器(看看您是否应该覆盖-从您继承的基类中获取它们)。

    【讨论】:

    • 非常感谢,这就是解决方案
    【解决方案2】:

    您是否考虑过使用NSTreeController?它有助于为您管理大纲视图并且非常方便。 NSTreeController 使用一个名为NSTreeNode 的类来表示大纲视图中的节点,每个NSTreeNode 都有一个representedObject 方法可以让您访问模型对象。

    无论如何,如果您不想使用NSTreeControllerNSTreeNode,您可以直接返回您的模型对象。以下是苹果指南中的一些示例 Objective-C 代码。

    @implementation DataSource
    // Data Source methods
    
    - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    
        return (item == nil) ? 1 : [item numberOfChildren];
    }
    
    
    - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
        return (item == nil) ? YES : ([item numberOfChildren] != -1);
    }
    
    
    - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    
        return (item == nil) ? [FileSystemItem rootItem] : [(FileSystemItem *)item childAtIndex:index];
    }
    
    
    - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
        return (item == nil) ? @"/" : [item relativePath];
    }
    
    @end
    
    
    @interface FileSystemItem : NSObject
    {
        NSString *relativePath;
        FileSystemItem *parent;
        NSMutableArray *children;
    }
    
    + (FileSystemItem *)rootItem;
    - (NSInteger)numberOfChildren;// Returns -1 for leaf nodes
    - (FileSystemItem *)childAtIndex:(NSUInteger)n; // Invalid to call on leaf nodes
    - (NSString *)fullPath;
    - (NSString *)relativePath;
    
    @end
    
    
    @implementation FileSystemItem
    
    static FileSystemItem *rootItem = nil;
    static NSMutableArray *leafNode = nil;
    
    + (void)initialize {
        if (self == [FileSystemItem class]) {
            leafNode = [[NSMutableArray alloc] init];
        }
    }
    
    - (id)initWithPath:(NSString *)path parent:(FileSystemItem *)parentItem {
        self = [super init];
        if (self) {
           relativePath = [[path lastPathComponent] copy];
           parent = parentItem;
           }
        return self;
    }
    
    
    + (FileSystemItem *)rootItem {
        if (rootItem == nil) {
            rootItem = [[FileSystemItem alloc] initWithPath:@"/" parent:nil];
        }
        return rootItem;
    }
    
    
    // Creates, caches, and returns the array of children
    // Loads children incrementally
    - (NSArray *)children {
    
        if (children == nil) {
            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSString *fullPath = [self fullPath];
            BOOL isDir, valid;
    
            valid = [fileManager fileExistsAtPath:fullPath isDirectory:&isDir];
    
            if (valid && isDir) {
                NSArray *array = [fileManager contentsOfDirectoryAtPath:fullPath error:NULL];
    
                NSUInteger numChildren, i;
    
                numChildren = [array count];
                children = [[NSMutableArray alloc] initWithCapacity:numChildren];
    
                for (i = 0; i < numChildren; i++)
                {
                    FileSystemItem *newChild = [[FileSystemItem alloc]
                                       initWithPath:[array objectAtIndex:i] parent:self];
                    [children addObject:newChild];
                    [newChild release];
                }
            }
            else {
                children = leafNode;
            }
        }
        return children;
    }
    
    
    - (NSString *)relativePath {
        return relativePath;
    }
    
    
    - (NSString *)fullPath {
        // If no parent, return our own relative path
        if (parent == nil) {
            return relativePath;
        }
    
        // recurse up the hierarchy, prepending each parent’s path
        return [[parent fullPath] stringByAppendingPathComponent:relativePath];
    }
    
    
    - (FileSystemItem *)childAtIndex:(NSUInteger)n {
        return [[self children] objectAtIndex:n];
    }
    
    
    - (NSInteger)numberOfChildren {
        NSArray *tmp = [self children];
        return (tmp == leafNode) ? (-1) : [tmp count];
    }
    
    
    - (void)dealloc {
        if (children != leafNode) {
            [children release];
        }
        [relativePath release];
        [super dealloc];
    }
    
    @end
    

    这不是 MonoMac,但应该是相同的想法。

    【讨论】:

    • 我明白你的意思,你也说我可以直接返回我的模型对象。当我这样做时,我得到一个 InvalidCastException,所以我认为这是 MonoMac 特有的问题。我会尝试 TreeController 的建议,但我认为它不会有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多