Michael Bedford Michael Bedford - 13 days ago 6
C# Question

EDIT - Xamarin Component Sortable Table View not sorting and several other issues

I have added the Sortable Table View to my project using the component store and have implemented it almost identical to the online documentation AND the sample application. The main difference of course is the data and data classes. So, basically, here is what I have. This gets called one time when the fragment comes in to onCreateView

string[] headers = { "Batch", "Posted", "Pkg Count", "Recipient" };
var tableHeaderAdapter = new SimpleTableHeaderAdapter(context, headers);
tableHeaderAdapter.SetTextColor(new Android.Graphics.Color(ContextCompat.GetColor(context, Resource.Color.lightText)));
tableHeaderAdapter.SetTextSize(10);

tableView.SetHeaderAdapter(tableHeaderAdapter);
tableView.SetHeaderBackgroundColor(new Android.Graphics.Color(ContextCompat.GetColor(context, Resource.Color.backgroundNormal)));

var rowColorEven = new Android.Graphics.Color(ContextCompat.GetColor(context, Resource.Color.altRowStyleLight));
var rowColorOdd = new Android.Graphics.Color(ContextCompat.GetColor(context, Resource.Color.altRowStyleDark));

tableView.SetDataRowColoriser(TableDataRowColorizers.AlternatingRows(rowColorEven, rowColorOdd));
tableView.HeaderSortStateViewProvider = SortStateViewProviders.BrightArrows();

var dMetrics = Resources.DisplayMetrics;
var width = (int)(dMetrics.WidthPixels * .97);

tableView.LayoutParameters.Width = width;

tableView.SetBackgroundColor(new Android.Graphics.Color(ContextCompat.GetColor(context, Resource.Color.backgroundLight)));

tableView.SetColumnWeight(0, 1);
tableView.SetColumnWeight(1, 1);
tableView.SetColumnWeight(2, 1);
tableView.SetColumnWeight(3, 1);

tableView.SetColumnComparator(0, new BatchIdComparator());
tableView.DataAdapter = new BatchTableDataAdapter(context, batchRecords);

tableView.DataClick += TableView_DataClick;


Now, I want to state that all seems to be working. What I mean by that is I do see the table and my data within. I also get the sort arrows on the first column header. The sort arrows appear to do things but here is where the issue lies. The first column is an integer, like a record ID. Let's say I have three records, 1, 2 and 3. When I click the sort arrows, I see them toggling but my records don't re-sort. They stay at 1, 2 and 3. However, the odd thing is if I put a break point in the TableView_DataClick method event handler and I click on the records, I can see that they are actually sorting even though it does not display that way. What I mean is if I click on column 1, which shows 1 and hit the break. I can see the data is actually for 1. However, if I click sort and then click column 1, which still shows 1, the data is actually 3 on the break. It almost seems as though it is not refreshing.

Am I missing something? Also, while we are on the top of refreshing, how do I manually initiate a refresh? I am going to add a refresh button below the table. If the data is modified outside of this class, I want the user to be able to click the refresh button and have the table update.

So to summarize, first I want to know why it appears to be sorting but doesn't reflect it on the view and second, how to manually initiate a refresh to pull in any new data that might be in there.

For the record, this is the BatchTableDataAdapter that I had to create. I suspect this is the issue since when this is instantiated, once on the onCreateView, the class returns all of the text views. Even though I sort later, this class would never get called again to re-return the views.

public class BatchTableDataAdapter : TableDataAdapter
{
Context oContext;
List<recBatch> batches;
const int textSize = 12;
public BatchTableDataAdapter(Context context, List<recBatch> Batches)
:base(context, Batches)
{
oContext = context;
batches = Batches;
}

public override View GetCellView(int rowIndex, int columnIndex, ViewGroup parentView)
{
var batchRecord = batches.ElementAt(rowIndex);

View renderedView = null;

switch (columnIndex)
{
case 0:
renderedView = renderBatchID(batchRecord);
break;
case 1:
renderedView = renderPosted(batchRecord);
break;
case 2:
renderedView = renderPkgCount(batchRecord);
break;
case 3:
renderedView = renderRecipient(batchRecord);
break;
}
return renderedView;
}

private View renderBatchID(recBatch batch)
{
var textView = new TextView(oContext);
textView.Text = batch.Batch.ToString();
textView.SetPadding(10, 5, 10, 5);
textView.TextSize = textSize;
return textView;
}

private View renderPosted(recBatch batch)
{
string posted = (string.IsNullOrEmpty(batch.Signature) ? "N" : "Y");
var textView = new TextView(oContext);
textView.Text = posted;
textView.SetPadding(10, 5, 10, 5);
textView.TextSize = textSize;
return textView;
}

private View renderPkgCount(recBatch batch)
{
var textView = new TextView(oContext);
textView.Text = batch.NumPackages.ToString();
textView.SetPadding(10, 5, 10, 5);
textView.TextSize = textSize;
return textView;
}

private View renderRecipient(recBatch batch)
{
var textView = new TextView(oContext);
textView.Text = batch.ToName;
textView.SetPadding(10, 5, 10, 5);
textView.TextSize = textSize;
return textView;
}
}


Finally, this is the compare on the first column, which is an integer. I can hit the break points and see that it does get called when I click the sort arrows and appears to be returning the correct numbers.

public class BatchIdComparator : Java.Lang.Object, Java.Util.IComparator
{
public int Compare(Java.Lang.Object lhs, Java.Lang.Object rhs)
{
var lhsCopy = CastJavaObject.Cast<recBatch>(lhs);
var rhsCopy = CastJavaObject.Cast<recBatch>(rhs);

if (lhsCopy.Batch < rhsCopy.Batch)
{
return -1;
}
if (lhsCopy.Batch > rhsCopy.Batch)
{
return 1;
}
return 0;
//return lhsCopy.Batch.CompareTo(rhsCopy.Batch);
}

}


EDIT: I am now having other issues. I had given up on the sorting but these other issues are frustrating me. If I had enough to offer for a bounty, I would. But, I don't have too much yet as I am new so I just ask, please help. Both of the SO posts and the Xamarin forums post have gone unanswered for 1.5 months.
Alright, still having issues on this and the thread here has gone for 1.5 months without an answer.


  1. I see and have tried to set the column weight but it would be nice if it would stretch automatically. There is too much guessing in setting the static weight and if you get it wrong, the table does not look right or you will get multiple lines in a row.

  2. I cannot get the table to scroll horizontally at all. Won't show scroll bars and won't scroll. I want the text to stay on one line, if it is longer than the control, then I want to scroll. If it won't stretch automatically, then I want to set the column wider than I will ever need and again, simply scroll.

  3. Long click does not actually work.

  4. There is no way to get the row you click on to highlight to a color to show it is selected.

  5. I would like to see grids or lines in between my columns.

  6. You cannot set a gravity for the text inside of the column so the alignment looks all out of whack. It would be nice to be able to left justify or center all of it. As with number 5, seeing the grid lines will also help make the table look clean and aligned.



Thanks!

Mike

Answer

To scroll horizontally this works for me.

<HorizontalScrollView android:layout_height="0dp" android:layout_weight="2" android:layout_width="wrap_content"> <de.codecrafters.tableview.SortableTableView android:id="@+id/tableView" android:layout_width="match_parent" android:layout_height="match_parent" app:headerElevation="10" app:headerColor="@color/primary" /> </HorizontalScrollView>

Comments