xamarin.formsgridcolumnspan

How to Set ColumnSpan in a Custom Grid in Xamarin.Forms


I've been developing a custom grid which has some attached properties. I can set rows and columns without problem but when I try to set columnspan, it does not effect.

In my example, I have

<akf:DynamicGridView Grid.Row="4">
  <Label akf:DynamicGridView.ItemWidth="*" Text="Item 1" BackgroundColor="Blue" />
  <Entry akf:DynamicGridView.ItemWidth ="*" Placeholder="Item 2"  BackgroundColor="Red"/>
  <Button akf:DynamicGridView.ItemRow="1" akf:DynamicGridView.ItemColumnSpan="2"  akf:DynamicGridView.ItemWidth ="*" Text="Item 3" BackgroundColor="Green" />
</akf:DynamicGridView>

The first two elements are placed in the first row with two columns and the last element is placed in the second row but ColumnSpan must be 2. But it behaves as default.

Here is my custom grid code

  public class DynamicGridView : Grid
  {
    public static readonly BindableProperty ItemWidthProperty = BindableProperty.CreateAttached( "ItemWidth", typeof( GridLength ), typeof( DynamicGridView ), GridLength.Auto );

    public static GridLength GetItemWidth( BindableObject view )
    {
      return (GridLength)view.GetValue( ItemWidthProperty );
    }

    public static void SetItemWidth( BindableObject view, GridLength value )
    {
      view.SetValue( ItemWidthProperty, value );
    }

    public static readonly BindableProperty ItemRowProperty = BindableProperty.CreateAttached( "ItemRow", typeof( int ), typeof( DynamicGridView ), 0 );

    public static int GetItemRow( BindableObject view )
    {
      return (int)view.GetValue( ItemRowProperty );
    }

    public static void SetItemRow( BindableObject view, int value )
    {
      view.SetValue( ItemRowProperty, value );
    }

    public static readonly BindableProperty ItemColumnSpanProperty = BindableProperty.CreateAttached( "ItemColumnSpan", typeof( int ), typeof( DynamicGridView ), 1 );

    public static int GetItemColumnSpan( BindableObject view )
    {
      return (int)view.GetValue( ItemColumnSpanProperty );
    }

    public static void SetItemColumnSpan( BindableObject view, int value )
    {
      view.SetValue( ItemColumnSpanProperty, value );
    }    


    public DynamicGridView()
    {
      Padding = 0;
      Margin = 0;
      ColumnSpacing = -1;
      RowSpacing = -1;

      _rowsAndColumns = new Dictionary<int, int>();
      this.ChildAdded += this.bar_ChildAdded;
    }

    Dictionary<int, int> _rowsAndColumns;
    private void bar_ChildAdded( object sender, ElementEventArgs e )
    {

      var view = e.Element as View;
      if( view != null )
      {

        var itemWidth = GetItemWidth( view);
        var itemRow = GetItemRow( view);
        var itemColumnSpan = GetItemColumnSpan(view);

        if( _rowsAndColumns.ContainsKey(itemRow))
        {
          _rowsAndColumns[ itemRow ]+=1;

        }
        else
        {
          _rowsAndColumns.Add( itemRow, 0 );
          RowDefinitions.Add( new RowDefinition() { Height= new GridLength( 1, GridUnitType.Auto) } );

        }

        if( itemColumnSpan > 1 )
        {
          SetColumnSpan( view, itemColumnSpan );             
        }

        if( _rowsAndColumns[itemRow] >= ColumnDefinitions.Count )
        {
          if( itemWidth.GridUnitType == GridUnitType.Absolute )
            ColumnDefinitions.Add( new ColumnDefinition() { Width = new GridLength( itemWidth.Value, itemWidth.GridUnitType ) } );
          else
            ColumnDefinitions.Add( new ColumnDefinition() { Width = new GridLength( 1, itemWidth.GridUnitType ) } );
        }    

        Children.Add( view, _rowsAndColumns[itemRow], itemRow );    
      }
    }
}

As you see in the code, if itemColumnSpan > 1 then I call SetColumnSpan method but it does not effect.

What is the problem in my code?


Solution

  • First, I assume you've used Breakpoint to verify that SetColumnSpan line is reached.

    Then, move column span set AFTER Children.Add. Add method sets ColumnSpan to default of 1.

    Children.Add( view, _rowsAndColumns[itemRow], itemRow );
    
    if( itemColumnSpan > 1 )
    {
        SetColumnSpan( view, itemColumnSpan );             
    }