Reputation: 320
I am creating new instance of grid object which have two labels as following.
<Grid x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70*"></ColumnDefinition>
<ColumnDefinition Width="30*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label x:Name="Label1" Text="Label1" Grid.Column="0" Grid.Row="0"></Label>
<Label x:Name="Label2" Text="Label2" Grid.Column="1" Grid.Row="0"></Label>
</Grid>
I am using Activator.CreateInstance method as given below:
Grid ClonedView =(Grid) Activator.CreateInstance(Grid.GetType());
foreach (PropertyInfo propertyInfo in Grid.GetType().GetProperties())
{
if (propertyInfo.CanRead && propertyInfo.CanWrite )
{
object PropertyValue = propertyInfo.GetValue(Grid, null);
propertyInfo.SetValue(ClonedView, PropertyValue);
}
}
When I use this ClonedView in my page, it Cloned Grid don't understand that Label2 should appear in second column of grid. I did a lot of research on it but could not find any solution. Please let me know if anybody has any solutions.
thanks
Upvotes: 0
Views: 218
Reputation:
They way you're thinking about this, feels very JavaScript like to me. You want to create a deep copy by copying all properties. However the Xamarin objects are way too complex for something like this (even if you where able to do a deep copy, Bindings for example won't work with simple copying).
So instead of making a single Grid
object and trying to create copies of it, another way of looking at it would be "I want to define a template, and then create multiple instances according to that template". For this Xamarin has the DataTemplate
class, which enables us to do something like this in xaml:
<ContentPage>
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="MyGridTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70*"></ColumnDefinition>
<ColumnDefinition Width="30*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Label Text="Label1" Grid.Column="0" Grid.Row="0"></Label>
<Label Text="Label2" Grid.Column="1" Grid.Row="0"></Label>
</Grid>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
<Button Text="Add Grid" Clicked="AddGridClicked">
</Button>
<StackLayout x:Name="GridHolder">
<StackLayout>
<ContentPage>
And in our code behind we can implement AddGridClicked
like this:
private void AddGridClicked(object sender, EventArgs e)
{
var myGridTemplate = (DataTemplate) Resources["MyGridTemplate"];
GridHolder.Children.Add((View)myGridTemplate.CreateContent());
}
Now the downside is that you need to define a DataTemplate
instead of just pointing at an object and saying getting a copy. Also keep in mind that x:Name
of a View
in the DataTemplate
can't be accessed in code behind of your page, but with a good Xamarin setup that should not be needed. The upside is that this works, complete with possible bindings, so you're allowed to define a Label
in your grid like this:
<Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0"></Label>
And then you can give each instance if your templated Grid
a different BindingContext
to bind different data to it's views.
Hope this helps
Upvotes: 1