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; }
}
}