How to create a custom grid control?

markmunizmarkmuniz USUniversity ✭✭
edited November 2015 in Xamarin.Forms

I am fairly new to Xamarin.Forms and MVVM. I currently have a method (using code from https://forums.xamarin.com/discussion/18475/is-it-possible-to-use-a-tableview-listview-to-function-similar-to-a-gridview) that will modify a grid element and dynamically insert elements from a list within a viewmodel, but I was only able to achieve this through code-behind. Is it possible to create a custom grid control which I can insert into any XAML that can bind to different viewmodels and get a list of data to create elements from all while staying MVVM compliant? The method to add to the grid is BuildTiles() which is called in the HomePage constructor:

public partial class HomePage : ContentPage
  {
    public HomePage()
    {
      InitializeComponent();
      BuildTiles();
    }

    public void BuildTiles()
    {

      var rowDef = new RowDefinition { Height = new GridLength(1.0, GridUnitType.Star) };
      var frames = new Collection<Tuple<Frame, int, int>>();

      for (var i = 0; i < HomeViewModel.Tiles.Count; i++)
      {
        var column = i % 2;
        var row = i / 2;
        frames.Add(new Tuple<Frame, int, int>(BuildGridElement(HomeViewModel.Tiles[i]), column, row));
      }

      // this has to run on the UI thread to prevent UI Locking.
      Device.BeginInvokeOnMainThread(() =>
      {
        TiledMenu.RowDefinitions.Clear();
        TiledMenu.Children.Clear();

        foreach (var frame in frames)
        {
          if (frame.Item3 % 2 != 0)
          {
            TiledMenu.RowDefinitions.Add(rowDef);
          }
          TiledMenu.Children.Add(frame.Item1, frame.Item2, frame.Item3);
        }
      });
    }

    private static Frame BuildGridElement(HomeViewModel.TileInfo value)
    {
      var titleLable = new Label
      {
        Text = value.Title,
        XAlign = TextAlignment.Center,
        YAlign = TextAlignment.Center,
        BackgroundColor = Color.Transparent,
        TextColor = Color.White
      };

      var innerLayout = new StackLayout
      {
        Children = { titleLable }
      };

      var palleteFrame = new Frame
      {
        BackgroundColor = Color.Blue,
        Content = innerLayout,
        HasShadow = false,
        VerticalOptions = LayoutOptions.FillAndExpand
      };

      palleteFrame.GestureRecognizers.Add(new TapGestureRecognizer((callback) => NavigateToSegment(value)));

      return palleteFrame;
    }
  }

Which will modify this XAML:

<Grid x:Name="TiledMenu"
              RowSpacing="1"
              ColumnSpacing="1">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
  </Grid>

with data from this viewmodel:

public class HomeViewModel : BaseViewModel
  {
    public HomeViewModel()
    {
      Tiles = new List<TileInfo>();
      Tiles.Add(new TileInfo() { Id = SomeID1, Title = String1 });
      Tiles.Add(new TileInfo() { Id = SomeID2, Title = String2 });
      Tiles.Add(new TileInfo() { Id = SomeID3, Title = String3 });
      Tiles.Add(new TileInfo() { Id = SomeID4, Title = String4 });
      Tiles.Add(new TileInfo() { Id = SomeID5, Title = String5 });
      Tiles.Add(new TileInfo() { Id = SomeID6, Title = Strings6 });
    }
    public static List<TileInfo> Tiles { get; set; }

    public class TileInfo
    {
      public int Id { get; set; }

      public string Title { get; set; }
    }
  }

Answers

Sign In or Register to comment.