I have a TableView with a custom UITableViewCell. In each cell I have multiple buttons, when any of the buttons is click after scrolling down and up it calls itself the many times I scroll down and up.
I have read and research for a solution and I haven't found a solution.
I know the problem is the cell are being reuse so that's why the buttons are being call multiple times but I can't find a way to prevent it.
I added console write line statements through the code and the else part in MoveToWindow is never call. Could that be the reason why?
Research material for solution:
my code is calling twice the btndelete method in uitableview
UIButton click event getting called multiple times inside custom UITableViewCell
My Code:
namespace Class.iOS
{
public partial class CustomCell : UITableViewCell
{
public static readonly NSString Key = new NSString ("CustomCell");
public static readonly UINib Nib;
public int Row { get; set; }
public event EventHandler LikeButtonPressed;
private void OnLikeButtonPressed()
{
if (LikeButtonPressed != null)
{
LikeButtonPressed(this, EventArgs.Empty);
}
}
public override void MovedToWindow()
{
if (Window != null)
{
btnAdd.TouchUpInside += HandleLikeButtonPressed;
}
else
{
btnAdd.TouchUpInside -= HandleLikeButtonPressed;
}
}
private void HandleLikeButtonPressed(object sender, EventArgs e)
{
OnLikeButtonPressed();
}
static CustomCell ()
{
Nib = UINib.FromName ("CustomCell", NSBundle.MainBundle);
}
public CustomCell ()
{
}
public CustomCell (IntPtr handle) : base (handle)
{
}
public void UpdateCell (string Name, int number)
{
// some code
}
public class TableSource : UITableViewSource
{
public override nint RowsInSection (UITableView tableview, nint section)
{
return 8;
}
private void HandleLikeButtonPressed(object sender, EventArgs e)
{
var cell = (CustomCell)sender;
var row = cell.Row;
switch (row)
{
case 0:
cell.label.Text = ""
break;
case 1:
cell.label.Text = ""
break;
}
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (CustomCell.Key) as CustomCell;
cell.Row = indexPath.Row;
if (cell == null)
{
cell = new CustomCell ();
var views = NSBundle.MainBundle.LoadNib("CustomCell", cell, null);
cell.LikeButtonPressed += HandleLikeButtonPressed;
cell = Runtime.GetNSObject( views.ValueAt(0) ) as CustomCell;
}
cell.UpdateCell
(
// some code
);
return cell;
}
}
}
}
The cells are reused in iOS, so you need to make sure you properly unhook handlers and reset state when a cell is reused. You can do something like this:
public partial class CustomCell : UITableViewCell {
EventHandler _likeButtonHandler;
public static readonly NSString Key = new NSString (typeof(CustomCell).Name);
public static readonly UINib Nib = UINib.FromName (typeof(CustomCell).Name, NSBundle.MainBundle);
public CustomCell ()
{
}
public CustomCell (IntPtr handle) : base (handle)
{
}
public override void PrepareForReuse ()
{
LikeButton.TouchUpInside -= _likeButtonHandler;
_likeButtonHandler = null;
base.PrepareForReuse ();
}
public void SetupCell (int row, string Name, EventHandler likeBtnHandler)
{
_likeButtonHandler = likeBtnHandler;
LikeButton.TouchUpInside += _likeButtonHandler;
LikeButton.Tag = row;
NameLabel.Text = Name;
RowLabel.Text = row.ToString ();
}
Notice that I unhook the event handler in the PrepareForReuse override. This is the correct place to do clean up and reset a cell for reuse. You should NOT be using MovedToWindow().
Then your GetCell method will look like this:
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (CustomCell.Key) as CustomCell ?? new CustomCell ();
cell.SetupCell (indexPath.Row, _fruits [indexPath.Row], _likeButtonHandler);
return cell;
}
The _likeButtonHandler is a simple EventHandler.
Related
I need the UIMenuItem to call a method inside the UITableViewCell. Something similar is possible in swift as explained here: https://stackoverflow.com/a/31358474/202179 .
At the moment I am only able to call the method inside the UIViewController from the UIMenuItem if I add an Export attribute to the method.
There is some trick in the export of this method in the cell, but I have failed to find it till now. I would expect this code to work, but it doesn't:
[Register("CustomCell")]
public class CustomCell : UITableViewCell
{
public CustomCell(IntPtr intPtr) : base(intPtr)
{
var menuItem = new UIMenuItem("Menu Item", new ObjCRuntime.Selector("CustomCell.SeekSelectedText"));
UIMenuController.SharedMenuController.MenuItems = new UIMenuItem[] { menuItem };
UIMenuController.SharedMenuController.Update();
}
[Export("SeekSelectedText")]
void SeekSelectedText()
{
//do something
}
}
As said just quoting a different selector inside the UIViewController works, so the problem is that this selector doesn't appear to be recognized whatever I try.
Here is my test and the custom UIMenuItem works fine.
First, define a custom cell class which inherits UITableViewCell
class MyCell: UITableViewCell
{
public MyCell(UITableViewCellStyle style, string reuseIdentifier):base(style, reuseIdentifier)
{
}
[Export("custom")]
void Custom()
{
//do something
Console.WriteLine("custom pop up");
}
public override bool CanPerform(Selector action, NSObject withSender)
{
if (action == new Selector("custom"))
return true;
else
return false;
}
}
Second, set the source of your UITableView
class MyTableViewSource : UITableViewSource
{
int i = 0;
// create custom cell
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
string cellStr = "cell";
MyCell cell = (MyCell)tableView.DequeueReusableCell(cellStr);
if (cell == null)
{
cell = new MyCell(UITableViewCellStyle.Subtitle, cellStr);
cell.TextLabel.Text = $"User Name {i}";
cell.DetailTextLabel.Text = $"details here... {i++}";
}
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return 10;
}
}
Then override the realted methods(e.g., ShouldShowMenu, CanPerformAction).
class MyTableViewDelegate : UITableViewDelegate
{
public override bool ShouldShowMenu(UITableView tableView, NSIndexPath rowAtindexPath)
{
return true;
}
public override bool CanPerformAction(UITableView tableView, Selector action, NSIndexPath indexPath, NSObject sender)
{
return true;
}
public override void PerformAction(UITableView tableView, Selector action, NSIndexPath indexPath, NSObject sender)
{
}
public override bool ShouldHighlightRow(UITableView tableView, NSIndexPath rowIndexPath)
{
return true;
}
}
Last, don't foget to add custom MenuItem to your UITableViewCell.
UIMenuController.SharedMenuController.MenuItems = new UIMenuItem[] {
new UIMenuItem ("Custom", new Selector ("custom"))
};
Since UICollectionView has similar functions to UITableVIew, you can directly refer to the sample SimpleCollectionView.
I am Working on Xamarin.iOS.In the TableView. I am bind the Cell with Button.
For Button Click I am doing Subscribe and Unsubscribe Cell event by below code
cell.btn_Click.Tag = indexPath.Row;
cell.btn_Click.TouchUpInside -= BtnClickEvent;
cell.btn_Click.TouchUpInside += BtnClickEvent;
this is not working fine when I call data api again and set to the TableView.
Explanation :
When I open ViewController first time cell button click event fire 1 time. And I open it second time it will fire cell button click event 2 time. I am using upper code for subscribe and unsubscribe button event then why it will called multiple time.
this issue i am facing in iOS 11.2
First Way :
Source Class full code
class StockListSourceClass : UITableViewSource
{
private List<PacketAndPacketDetailItem> stockLists;
private List<string> serialNoList;
private UINavigationController navigationController;
public static event EventHandler BtnClickEvented;
public StockListSourceClass(List<PacketAndPacketDetailItem> stockLists, List<string> serialNolist, UINavigationController navigationController)
{
this.stockLists = stockLists;
this.serialNoList = serialNolist;
this.navigationController = navigationController;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
StockTableViewCell cell = tableView.DequeueReusableCell(StockTableViewCell.Key) as StockTableViewCell ?? StockTableViewCell.Create();
var item = stockLists[indexPath.Row];
if (serialNoList.Contains(item.SerialNo))
cell.BindData(item, true);
else
cell.BindData(item, false);
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
cell.PreservesSuperviewLayoutMargins = false;
cell.SeparatorInset = UIEdgeInsets.Zero;
cell.LayoutMargins = UIEdgeInsets.Zero;
cell.SetNeedsLayout();
cell.LayoutIfNeeded();
cell.btn_Click.Tag = indexPath.Row;
cell.btn_Click.TouchUpInside -= BtnClickEvent;
cell.btn_Click.TouchUpInside += BtnClickEvent;
cell.btn_Click.TouchUpInside += (sender, e) => {
var imageName = ((UIButton)sender).TitleLabel.Text;
if (imageName.Equals("unchecked"))
{
((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("checked"), UIControlState.Normal);
((UIButton)sender).TitleLabel.Text = "checked";
}
else
{
((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("unchecked"), UIControlState.Normal);
((UIButton)sender).TitleLabel.Text = "unchecked";
}
};
return cell;
}
public void BtnClickEvent(object sender, EventArgs e)
{
var row = ((UIButton)sender).Tag;
MarketSheetViewController.RowNo = (int)row;
if (BtnClickEvented != null)
{
BtnClickEvented(stockLists[(int)row].SerialNo, EventArgs.Empty);
}
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return stockLists.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var storyboard = UIStoryboard.FromName("Main", null);
var webController = storyboard.InstantiateViewController("PacketDetailViewController") as PacketDetailViewController;
webController.item = stockLists[indexPath.Row];
this.navigationController.PushViewController(webController, true);
}
}
Inside ViewController I use that
StockListSourceClass.BtnClickEvented += (sender, e) =>
{
if (!(serialNoList.Contains(stockLists[RowNo].SerialNo)))
serialNoList.Add(stockLists[RowNo].SerialNo);
else
serialNoList.Remove(stockLists[RowNo].SerialNo);
SetUpperPanelData();
};
Second way
cell.btn_Click.TouchUpInside += (sender, e) => {
var imageName = ((UIButton)sender).TitleLabel.Text;
if (imageName.Equals("unchecked"))
{
((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("checked"), UIControlState.Normal);
((UIButton)sender).TitleLabel.Text = "checked";
}
else
{
((UIButton)sender).SetBackgroundImage(UIImage.FromBundle("unchecked"), UIControlState.Normal);
((UIButton)sender).TitleLabel.Text = "unchecked";
}
var row = ((UIButton)sender).Tag;
MarketSheetViewController.RowNo = (int)row;
if (BtnClickEvented != null)
{
BtnClickEvented(stockLists[(int)row].SerialNo, EventArgs.Empty);
}
};
But this method is called multiple times if I open the ViewController a second time.
Finally got the solution by doing below way
StockTableViewCell.cs
public partial class StockTableViewCell : UITableViewCell
{
public int Row;
public event EventHandler<int> SelectButtonTapped;
public void BindData(PacketAndPacketDetailItem item, bool flag, int row)
{
this.Row = row;
btn_click.TouchUpInside -= OnSelectButtonTapped;
btn_click.TouchUpInside += OnSelectButtonTapped;
}
private void OnSelectButtonTapped(object sender, EventArgs e)
{
if (SelectButtonTapped != null)
SelectButtonTapped(sender, Row);
}
}
TableSource Class
class StockListSourceClass : UITableViewSource
{
public event EventHandler<int> SelectButtonTapped;
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
StockTableViewCell cell = tableView.DequeueReusableCell(StockTableViewCell.Key) as StockTableViewCell ?? StockTableViewCell.Create();
var item = stockLists[indexPath.Row];
if (serialNoList.Contains(item.SerialNo))
cell.BindData(item, true, indexPath.Row);
else
cell.BindData(item, false, indexPath.Row);
cell.SelectButtonTapped -= OnCellSpeakButtonTapped;
cell.SelectButtonTapped += OnCellSpeakButtonTapped;
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
cell.PreservesSuperviewLayoutMargins = false;
cell.SeparatorInset = UIEdgeInsets.Zero;
cell.LayoutMargins = UIEdgeInsets.Zero;
cell.SetNeedsLayout();
cell.LayoutIfNeeded();
return cell;
}
void OnCellSpeakButtonTapped(object sender, int e)
{
var row = e;
MarketSheetViewController.RowNo = (int)row;
if (SelectButtonTapped != null)
SelectButtonTapped(sender, e);
}
}
and finally we can do in the ViewController to get the single event of Cell button
define this way
stockListSourceClass.SelectButtonTapped -= OnSelectButtonTapped;
stockListSourceClass.SelectButtonTapped += OnSelectButtonTapped;
and Implement it.
private void OnSelectButtonTapped(object sender, int e)
{
if (!(serialNoList.Contains(stockLists[RowNo].SerialNo)))
serialNoList.Add(stockLists[RowNo].SerialNo);
else
serialNoList.Remove(stockLists[RowNo].SerialNo);
SetUpperPanelData();
}
You can try to place that code inside your custom cell, unsubscribe event inside method PrepareForReuse and subscribe it when populating the data to cell.
Code
public class DetailCell : UICollectionViewCell
{
CustomEventHandler HandlerForButton;
public override void PrepareForReuse ()
{
base.PrepareForReuse ();
if (HandlerForButton != null)
{
EditButton.TouchUpInside -= ButtonPressed;
}
HandlerForButton = null;
}
private void ButtonPressed (object sender, EventArgs args)
{
if (HandlerForButton != null)
{
HandlerForButton (this, args);
}
}
internal void GetCell (int position, CustomEventHandler handler)
{
HandlerForButton = handler;
EditButton.TouchUpInside += ButtonPressed;
}
}
public class CollectionViewSource : UICollectionViewSource
{
public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = collectionView.DequeueReusableCell ("DetailCell", null) as DetailCell;
cell.GetCell (indexPath.Row, ClickHandler);
return cell;
}
private void ClickHandler (UICollectionViewCell sender, CustomEventArgs args)
{
var cell = sender as UICollectionViewCell;
if (cell != null)
{
// do stuff
}
var yourArgs = args as CustomEventArgs;
if (yourArgs != null)
{
// do stuff
}
}
}
internal delegate void CustomEventHandler (DetailCell sender, CustomEventArgs args);
Details refer to here.
I have two UITableView in the same UIViewController.
tblView1 & tblView2.
Both TableViews are bringing data dynamically.
Now my problem is: I want to load data in tblView2 on the basis of SelectedRow from tblView1.
For Example, when I select a company name from tblView1, then tblView2 needs to populate the Cars made by that company.
I have rowIndex of my first table (tblView1), but i can't bind my tblView2 from the RowSelected Method of tblView1.
I need help in binding my tblView2. How can i do this?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using CoreGraphics;
using Foundation;
using UIKit;
namespace Tables
{
public partial class ViewController : UIViewController
{
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public ViewController()
{
//tblView2.Source = new CompanyModelsSource();
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
if (tblView1 != null)
{
tblView1.Source = new CarModelsSource();
}
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
class CompanyModelsSource : UITableViewSource
{
private List<Companies> _Companies;
NSString _cellID = new NSString("TableCell");
public CompanyModelsSource()
{
_Companies = CompanyTableSource.AllCompany();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
// tell the TableView how many rows to create
return _Companies.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
//I can't access my tblView2 in this method. So where i can bind my other UITableView?
UILabel lblTotalFacilities = new UILabel();
lblTotalFacilities.Layer.BackgroundColor = UIColor.Blue.CGColor;
lblTotalFacilities.Frame = new CGRect(305, 200, 1024, 400);
ViewController vc = new ViewController();
vc.View.AddSubview(lblTotalFacilities);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
Company currentCompany = _Companies[indexPath.Row];
var cell = tableView.DequeueReusableCell(_cellID) as CompanyTableCell;
if (cell == null) { cell = new CompanyTableCell(_cellID); }
cell.UpdateCellControlsWithAuditData(currentCompany.Name);
return cell;
}
}
public class CompanyTableSource
{
public CompanyTableSource()
{
}
public static List<Companies> AllCompany()
{
CompanyCollection CC = null;
string path1 = path + "Companies.xml";
XmlSerializer serializer = new XmlSerializer(typeof(CompanyCollection));
StreamReader reader = new StreamReader(path1);
CC = (CompanyCollection)serializer.Deserialize(reader);
reader.Close();
List<Companies> comp = CC.CompanyCollection.Cast<Companies>().ToList();
return comp;
}
}
public class CompanyTableCell : UITableViewCell
{
UILabel nameLabel;
public CompanyTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(54, 194, 36);
var newFont = UIFont.SystemFontOfSize(12);
nameLabel = new UILabel();
nameLabel.Font = newFont;
ContentView.AddSubviews(new UIView[] { nameLabel });
}
public void UpdateCellControlsWithAuditData(string Name)
{
nameLabel.Text = Name;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
nameLabel.Frame = new CGRect(10, 0, 350, 33);
}
}
}
Hope this helps. Created everything in a single file for simplicity.
public partial class ViewController : UIViewController
{
public ViewController() : base("ViewController", null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
var companySource = new CompanyTableSource();
tblView1.Source = companySource;
companySource.ItemSelected += OnCompanyItemSelected;
}
//this will handle the ItemSelected event
//here you will retrieve the data for the second UITableView
void OnCompanyItemSelected(object sender, Company e)
{
//you can do it this way
tblView2.Source = new CarTableSource(e.Id);
List<Car> cars = GetCarsByCompanyId(e.Id);
//or this whay
tblView2.Source = new CarTableSource(cars);
}
List<Car> GetCarsByCompanyId(int id)
{
//Your logic to get the data goes here
throw new NotImplementedException();
}
}
public class CompanyTableSource : UITableViewSource
{
// You can use the whole object or just an integer (companyId)
public event EventHandler<Company> ItemSelected;
public IList<Company> Items { get; private set; } = new List<Company>();
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var item = Items[indexPath.Row];
ItemSelected?.Invoke(this, item);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
//Do your implementation
throw new NotImplementedException();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return Items.Count;
}
}
public class CarTableSource : UITableViewSource
{
public IList<Car> Items { get; private set; } = new List<Car>();
public CarTableSource(int companyId)
{
//Get your data based on the companyId
}
//Or pass in the data already retreived. (I preffer this method)
public CarTableSource(IList<Car> cars)
{
Items = cars;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
//Do your implementation
throw new NotImplementedException();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return Items.Count;
}
}
I'm trying to apply an event to a cell in order to specify the TouchesBegan method.
cell.TouchesBegan += OnTouchesBegan;
But TouchesBegan is a method group and not an event.
How do I add custom behavior to a Cells TouchesBegan() method in monotouch?
[Register("MenuView")]
public class MenuView : ViewControllerBase
{
private new MenuViewModel ViewModel { get { return (MenuViewModel)base.ViewModel; } }
public override void ViewDidLoad()
{
base.ViewDidLoad();
// this ensures the sliding panel doesn't fill the entire view.
var frame = View.Frame;
frame.Width = 300;
View.Frame = frame;
var chapters = ViewModel.Chapters;
//var listHeight = (chapters.Count*40);
var navigationList = new UITableView(new RectangleF(0, 50, 300, 300))
{
Source = new NavigationTableSource(chapters)
};
Add(navigationList);
}
}
public class NavigationTableSource : UITableViewSource
{
private readonly IList<ChapterViewModel> _chapters;
private const string CellIdentifier = "NavigationCell";
public NavigationTableSource(IList<ChapterViewModel> chapters)
{
_chapters = chapters;
}
public override int RowsInSection(UITableView tableview, int section)
{
return _chapters.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
// if there are no cells to reuse, create a new one
cell.TextLabel.Text = _chapters[indexPath.Row].Title;
cell.TouchesBegan += OnTouchesBegan;
return cell;
}
}
TouchesBegan is a method that you can override by subclassing UITableViewCell:
public class CustomCell : UITableViewCell
{
public CustomCell(UITableViewCellStyle style, NSString reuseIdentifier) : base(style, reuseIdentifier)
{
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
// do something
base.TouchesBegan(touches, evt);
}
}
Then use your subclass when creating a cell:
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new CustomCell(UITableViewCellStyle.Default, CellIdentifier);
So the way I was able to manage this was to SubClass my UITableViewSource. In there I overrode RowSelected(UITableView tableView, NSIndexPath indexPath)
public class NavigationTableSource : UITableViewSource
{
private readonly IList<ChapterViewModel> _chapters;
private const string CellIdentifier = "NavigationCell";
public NavigationTableSource(IList<ChapterViewModel> chapters)
{
_chapters = chapters;
}
public override int RowsInSection(UITableView tableview, int section)
{
return _chapters.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
// todo: This is where we're going to load up the appropriate chapter.
new UIAlertView("Row Selected", _chapters[indexPath.Row].Title, null, "OK", null).Show();
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
// if there are no cells to reuse, create a new one
cell.TextLabel.Text = _chapters[indexPath.Row].Title;
return cell;
}
}
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!