Ravi
Ravi

Reputation: 320

Copy attached properties to new instance in xamarin forms

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

Answers (1)

user10608418
user10608418

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

Related Questions