将附加属性复制到xamarin形式的新实例中

时间:2019-04-26 11:58:23

标签: xamarin.forms system.reflection

我正在创建具有以下两个标签的网格对象的新实例。

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

我正在使用Activator.CreateInstance方法,如下所示:

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

                }
            }

当我在页面中使用此ClonedView时,它的Cloned Grid无法理解Label2应该出现在网格的第二列中。我对此进行了大量研究,但找不到任何解决方案。请让我知道是否有人可以解决。

谢谢

1 个答案:

答案 0 :(得分:1)

您以这种方式思考的方式,对我来说就像JavaScript。您想通过复制所有属性来创建深层副本。但是,对于这样的事情,Xamarin对象太复杂了(即使您能够进行深层复制,例如Bindings也不适用于简单复制)。

因此,与其制作单个Grid对象并尝试创建它的副本,不如查看它的另一种方式是“我想定义一个模板,然后根据该模板创建多个实例”。为此,Xamarin具有DataTemplate类,这使我们能够在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>

在后面的代码中,我们可以像这样实现AddGridClicked

private void AddGridClicked(object sender, EventArgs e)
{
    var myGridTemplate = (DataTemplate) Resources["MyGridTemplate"];
    GridHolder.Children.Add((View)myGridTemplate.CreateContent());
}

现在的缺点是,您需要定义一个DataTemplate而不是仅指向一个对象并说要获得副本。还要记住,x:NameView中的DataTemplate不能用页面后面的代码来访问,但是具有良好的Xamarin设置是不必要的。这样做的好处是,它可以完成可能的绑定,因此您可以像这样在网格中定义Label

<Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0"></Label>

然后,如果您将模板化的Grid设为不同的BindingContext,则可以为每个实例赋予不同的数据,以将不同的数据绑定到其视图。

希望这会有所帮助