سؤال

I'm trying to implement a datasource for an NSOutlineView. The problem is that I don't know what type of object to return from outlineView:child:ofItem:.

Current code looks like this:

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

With MyItem:

public class MyItem : NSObject
{}

EDIT: With this code, I get an InvalidCastException just after returning MyItem.

هل كانت مفيدة؟

المحلول

If you inherit a new type from NSOutlineViewDataSource then you should not re-export its outlineView:child:ofItem: selector on your own method. Instead what you should do is override the GetChild method that already export this selector, e.g.

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

Note: that might not help since I have not tried it (I mostly do MonoTouch things) but do review other selectors you might be redefining/exporting in your application (to see if you should not be override-ing them from the base class you're inheriting from).

نصائح أخرى

Have you considered using a NSTreeController? It helps manage the outline view for you and is very handy. NSTreeController uses a class called NSTreeNode to represent nodes in the outline view, and each NSTreeNode has a representedObject method that allow you to get to the model object.

In any case, if you don't want to use the NSTreeController or NSTreeNode, you can just return your model object directly. Here are some sample Objective-C code from apple guides.

@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

It isn't MonoMac but should be the same idea.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top