Xamarin Forms Grid conditional RowSpan - xamarin.forms

I have a generic Grid List Control. Which let me Bind the Item Source and ItemTemplate and it will generates the Column and Rows based on Number of Items or Based on how Users set the Rows and Columns. Its perfect until here. It supports all the generics I needed.
Now the Problem part:
I have a ContentView which will be used as Item Template for the Grid. This Template will be used for Multiple Data Types. I'm able to do it properly. Now I have one Data Type Where the First Cell should have RowSpan if it meets certain condition: The code below works perfect. It creates the RowSpan perfectly.
bool isYearBuilt = false;
bool isAny = false;
public FilterItemView()
{
InitializeComponent();
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var context = BindingContext as PropertyFilterItem;
if (context == null)
return;
if(context.FilterType==PropertyFilterTypes.YearBuilt)
{
if(context.IsAny)
{
isYearBuilt = true; isAny = true;
}
}
}
protected override void OnParentSet()
{
base.OnParentSet();
GridList grid = this.Parent as GridList;
if (grid == null)
return;
if(isYearBuilt && isAny)
{
Grid.SetRowSpan(this, 2);
}
}
These are the Images; which will describe it more perfectly:
This is how it looks based on above code. We can see that it is creating RowSpan.
This is what I'm expecting to do.
The only problem is - While Setting RowSpan it is not refreshing the subsequent cells. Because, I'm applying the RowSpan in Runtime after the Grid and all the Cells are created. How can I refresh the Grid and other remaining cells to moved to their own cells?
Thank you for helping me.

Set the grid list's ItemsSource = null and set it back again to the item source you want.

Cause of the problem:
As you have said, While Setting RowSpan it is not refreshing the subsequent cells.
Solution:
After you have set rowspan using Grid.SetRowSpan(this, 2); you have to bind the datasource again.

Since I had my own Custom Grid List control. I implemented more Properties which let me know When I have to RowSpan for Child View in Grid and Adjust subsequent Child items. That was the only best way to deal with this problem rather than re-assigning the ItemSource property. Because, If we assign item source it will redraw all the items (including the rows and columns - not row/colspans). So we would still end up with same issue.
Solution: Added RowSpan logic in my Grid Control.

Related

How to simple overwrite showContextMenu on all columns of a grid?

If I overwrite showContextMenu on a grid it only add additional menu to the pop up menu when I click on a grid but do not click on any column. One way is to overwrite showContextMenu on all columns in grid but this solution does not looks right. Is there some better way how to insertItem to showContextMenu on all columns of a grid?
I am using AX 2012.
Standard code works only if grid is clicked but not a single column of a grid.
int ret,ii;
int myMenu = 2;
PopupMenu popupMenu = PopupMenu::create(_menuHandle);
FormListItem item;
;
deleteAttachment = popupMenu.insertItem('My menu');
ret = super(_menuHandle);
if(ret == myMenu)
{
//My code
}
return ret;
You need to use method registerOverrideMethod.
You can test how it works as follows. E.g. you have a form with a grid (property Name = 'Grid', AutoDeclaration = 'Yes'), and there are a few StringEdit controls in that grid.
1) Create following method in your form:
public void formControlContext(FormStringControl _formStringControl)
{
_formStringControl.context();
info(strFmt(#"Overridden context of control '%1'", _formStringControl.name()));
}
2) Override method init in your form:
public void init()
{
FormStringControl fsc;
int controlNum;
super();
for (controlNum = 1; controlNum <= Grid.controlCount(); controlNum++)
{
fsc = Grid.controlNum(controlNum);
fsc.registerOverrideMethod(methodStr(FormStringControl, context), identifierStr(formControlContext));
}
}
You only need to modify method 'formControlContext' according to your needs.
P.S. I just noticed you need to override method showContextMenu anot not context. The idea is the same - use registerOverrideMethod. You can override any method this way.
I've never played with overwriting the ShowContextMenu, but I did just make a blog post about how to recursively loop over every form control that sounds like it might help you.
http://alexondax.blogspot.com/2014/05/how-to-use-recursion-to-loop-over-form.html
I'd imagine you could create some sort of handler and key/value thing if you're creative.

Devexpress ASPxGridView New Row Disabled

I have code like this with devexpress ASPxGridView. Everything goes well, but when I try to add new row, new row's textbox is disabled...
I have KeyFieldName set.
void BindGrid()
{
var AnnObj = SearchBarBanners.Select(i => new
{
Caption = i.Attribute("caption").Value,
ID = i.Attribute("id").Value, // this is generated by Guid
}).ToList();
ImagesGrid.DataSource = AnnObj;
ImagesGrid.DataBind();
}
I can suggest you two things without grid markup:
1. Call BindGrid method in Page_Init
2. If your datasource initially returns zero rows, grid won't be able to determine type of objects that will be rendered in grid. You need to use ASPxGridView.ForceDataRowType in order to solve this problem.
Use recommendations from the Q392961 DX Article to resolve this issue.

DevExpress XtraGrid FocusedRowChanged event problem when changing datasource

This problem has bugged me for several years and maybe someone here knows a simple solution, since I just ran into it again.
QUESTION: Is there any way to get the XtraGrid to "forget" the current focused row index before a new (different) datasource is assigned to the grid?
BACKGROUND
We use the XtraGrid as a kind of controller for what is displayed in another panel of a multipane Winform.
Now imagine a hypothetical scenario where the datasource of the XtraGrid keeps changing according to menu selections. Menu item 1 populates the grid with a list of today's entrees in the cafeteria: Id, Name. Menu item 2 populates the grid with a list of Customers the user must phone that day: ID, Name. Important thing is that these are separate distinct datasources, and the grid's datasource is being assigned and reassigned.
CRITICAL FACT FOR THIS QUESTION:
We want the grid's FocusedRowChanged event to be the single place where we trap the user's selection in the controller grid. We are a "no spaghetti code" shop. FocusedRowChanged is better than a click event because it handles keyboard navigation too. The row with the focus contains the ID of the detail record we need to fetch from the database for display in Panel #2. This works--most of the time.
Here's how it doesn't work: let's say that on a given day, the list of customers the user must contact contains only one row. So the first (and only) row in the grid is the focused row. Now let's say that the user goes up to the menu and selects the menu item to display the day's cafeteria entrees. When the user clicks on the first item in the Entrees list, the FocusedRowChanged event does NOT fire because the grid has retained a memory of the focused row index from the previous datasource. The focused row index has not changed. And thus the user's selection doesn't trigger anything.
I tried to get DevExpress to offer a second more row-object-oriented mode (as distinct from row-index-oriented approach) whereby each row in the grid would have a GUID, and the FocusedRowChanged event would fire whenever the GUID of the currently focused row differed from the GUID of the previously focused row, regardless of whether the focused row index happened to be the same. This would allow dynamic changes of datasource and enable the desired behavior. But they demurred.
So I'll ask my question again, Is there any way to get the XtraGrid to "forget" the current focused row index before a new datasource is assigned to the grid?
Tim, I had the exact same problem when the grid only had one row of data in it and then changed data sources. I solved it by setting the gridview.FocusedRowHandle = -1 after setting the new datasource.
In a similar situation, I am subscribing to the
FocusedRowObjectChanged
event (using DevExpress 16.1).
I think that the best solution to this problem is to create a new GridView object and override its DoChangeFocusedRowInternal method. Below you will find the default implementation of this method. All you need to do is to change the marked row just as your needs dictate. Also, take a look at the How to create a GridView descendant class and register it for design-time use article, it contains some useful information.
public class MyGridView : GridView {
protected override void DoChangeFocusedRowInternal(int newRowHandle, bool updateCurrentRow) {
if(this.lockFocusedRowChange != 0) return;
if(!IsValidRowHandle(newRowHandle))
newRowHandle = DevExpress.Data.DataController.InvalidRow;
if(FocusedRowHandle == newRowHandle) return; // <<<<<<
int currentRowHandle = FocusedRowHandle;
BeginLockFocusedRowChange();
try {
DoChangeFocusedRow(FocusedRowHandle, newRowHandle, updateCurrentRow);
}
finally {
EndLockFocusedRowChange();
}
RaiseFocusedRowChanged(currentRowHandle, newRowHandle);
}
}
UPDATE
My code:
namespace MyXtraGrid {
public class MyGridControl : GridControl {
protected override BaseView CreateDefaultView() {
return CreateView("MyGridView");
}
protected override void RegisterAvailableViewsCore(InfoCollection collection) {
base.RegisterAvailableViewsCore(collection);
collection.Add(new MyGridViewInfoRegistrator());
}
}
public class MyGridViewInfoRegistrator : GridInfoRegistrator {
public override string ViewName { get { return "MyGridView"; } }
public override BaseView CreateView(GridControl grid) {
return new MyGridView(grid as GridControl);
}
}
public class MyGridView : GridView {
public MyGridView(GridControl ownerGrid) : base(ownerGrid) { }
public MyGridView() { }
protected virtual bool RowEqual(int focusedRowHandle, int newRowHandle) {
if(IsDesignMode)
return focusedRowHandle == newRowHandle;
DataRow row1 = GetDataRow(focusedRowHandle);
DataRow row2 = GetDataRow(newRowHandle);
return row1 == row2;
}
protected override void DoChangeFocusedRowInternal(int newRowHandle, bool updateCurrentRow) {
if(this.lockFocusedRowChange != 0) return;
if(!IsValidRowHandle(newRowHandle))
newRowHandle = DevExpress.Data.DataController.InvalidRow;
if(RowEqual(FocusedRowHandle, newRowHandle))
return;
int currentRowHandle = FocusedRowHandle;
BeginLockFocusedRowChange();
try {
DoChangeFocusedRow(FocusedRowHandle, newRowHandle, updateCurrentRow);
}
finally {
EndLockFocusedRowChange();
}
RaiseFocusedRowChanged(currentRowHandle, newRowHandle);
}
}
}
You can subscribe on the DataSourceChanged event which will fire when Data source changes (you guessed it!) so then you can get using GetFocusedObject() the object and display the relevant items for the other grid...

Flex DataGrid List highlighting

By default, whenever you rollOver/mouseOver (not sure of the difference) an item in a Datagrid or a List, that item is highlighted with the component's rollOverColor. I'm just wondering if there's any way to do that programmatically. I haven't been able to find much help on the issue. For example, suppose I have two DataGrids. When I rollOver an item in the first DataGrid, I want to highlight the corresponding index in the second one as well. Basically, as if two separate cursors were rollOver'ing two separate DataGrids. How can I do this?
Ian
You can listen for the datagrid's itemRollOver event and then select a row in the other datagrid by using it's selectedIndex or selectedItem properties.
1) Create a custom DataGrid with this function :
public function indicesToItemRenderer(rowIndex:int, colIndex:int):IListItemRenderer
{
var firstItemIndex:int = verticalScrollPosition - offscreenExtraRowsTop;
if (rowIndex < firstItemIndex ||
rowIndex >= firstItemIndex + listItems.length
)
{
return null;
}
return listItems[rowIndex - firstItemIndex][colIndex];
}
2) When you want to hightlight an item, call this code :
youCustomADG.indicesToItemRenderer(idxRow, idxCol).dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER);

How to use 2 different item renderers in mx:Tree

Question for Flex guys.
How can I use multiple item renderers in mx:Tree depending on item's depth/level in tree?
For example. For the first level items I want to use label with button and for second level items combobox.
Is this somehow possible?
Here is solution:
In extended Tree just override function getItemRendererFactory(data:Object):IFactory and do neccessary logic to select proper itemRenderer.
Hope this will help also someone else
That conditional logic should be implemented in a single itemrenderer. You can't set multiple renderers.
Here is a receipe how this can be implemented: http://cookbooks.adobe.com/post_How_do_I_create_a_Tree_itemRenderer_-62.html
override public function set data(value:Object):void
{
if(value != null)
{
super.data = value;
if(TreeListData(super.listData).hasChildren)
{
setStyle("color", 0x660099);
setStyle("fontWeight", 'bold');
}
else
{
setStyle("color", 0x000000);
setStyle("fontWeight", 'normal');
}
}
}
That 'if' statement shows you if you have inner nodes or not. You also can specify additional property when generating the data provider.

Resources