Event Handling UITableViewSource for iOS with Mono

2020-06-29 07:46发布

问题:

I'm trying to capture and handle an event when an element of a UITableViewSource is clicked.
Here's my code:

    public class TableViewSource : UITableViewSource
    {
        public event EventHandler<SongSelectedEventArgs> SongSelected;
        private List<Song> rows;

        public TableViewSource (List<Song> list) 
        { 
            rows = list; 
        }

        public override int RowsInSection (UITableView tableview, int section) 
        { 
            return rows.Count; 
        }

        public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
            // raise our event
            var handler = SongSelected;
            if (handler != null)
                handler (this, new SongSelectedEventArgs (rows[indexPath.Row]));
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {  
            UITableViewCell cell = new UITableViewCell(UITableViewCellStyle.Default,"mycell"); 
            cell.TextLabel.Text = rows[indexPath.Row].ToString();
            return cell;
        }

        public class SongSelectedEventArgs : EventArgs
        {
            public Song Group { get; set; }
            public SongSelectedEventArgs(Song group) : base()
            { Group = group; }
        }
    }

I'm modeling from an example piece from Xamarin, here:

    protected class AssetGroupTableSource : UITableViewSource
    {
        public event EventHandler<GroupSelectedEventArgs> GroupSelected;
        protected List<ALAssetsGroup> groups;

        public AssetGroupTableSource(List<ALAssetsGroup> groups) { this.groups = groups; }

        public override int NumberOfSections (UITableView tableView) { return 1; }

        public override int RowsInSection (UITableView tableview, int section) { return groups.Count; }

        public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
        {
            UITableViewCell cell = tableView.DequeueReusableCell ("AlbumCell");
            if(cell == null)
                cell = new UITableViewCell (UITableViewCellStyle.Default, "AlbumCell");
            cell.TextLabel.Text = groups[indexPath.Row].Name;
            return cell;
        }

        public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
            // raise our event
            var handler = GroupSelected;
            if (handler != null)
                handler (this, new GroupSelectedEventArgs (groups[indexPath.Row]));
        }

        public class GroupSelectedEventArgs : EventArgs
        {
            public ALAssetsGroup Group { get; set; }
            public GroupSelectedEventArgs(ALAssetsGroup group) : base()
            { Group = group; }
        }
    }

When I click on an element (of class Song) in the table view, it successfully goes to the override RowSelected. However, the handler is always null. What am I doing differently from the example code that is causing this to fail?

EDIT: Here is the line that should read the event (but isn't triggering):

    TableViewSource tableData = new TableViewSource(results);

        tableData.SongSelected += (object sender, TableViewSource.SongSelectedEventArgs e) => {
            //AssetEnumerationScreen assetScreen = new AssetEnumerationScreen (e.Group.Name, assetGroups[e.Group]);
            //NavigationController.PushViewController (assetScreen, true);
            Console.WriteLine("Test");
        };

EDIT: Here is most of the main body code:

    TableViewSource tableData = new TableViewSource(results);

        tableData.SongSelected += (object sender, TableViewSource.SongSelectedEventArgs e) => {
            Console.WriteLine("Test");
        };

        tableData.SongSelected += delegate(object sender, TableViewSource.SongSelectedEventArgs e) {
            Console.WriteLine("Test");
            LyricsScreen assetScreen = new LyricsScreen (e.Song);
            NavigationController.PushViewController (assetScreen, true);
        };
        searchBool.ValueChanged += (sender, e) => {
            UpdateDisplay(tableData, songList);
        };
        lyricSearch.TextChanged += (sender, e) => {
            UpdateDisplay(tableData, songList);
        };

        lyricSearch.Text = String.Empty;

        this.searchResults.Source = tableData;

EDIT!: I found the mistake. I had this line:

    tableData = new TableViewSource(results);

twice, so it subscribes the first one to the event, but then I created a new one and set that one to the source, overwriting the one with the subscription.

Thanks!