将附加属性复制到 xamarin 表单中的新实例

Copy attached properties to new instance in xamarin forms

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

<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 应出现在网格的第二列中。我对此进行了大量研究,但找不到任何解决方案。如果有人有任何解决方案,请告诉我。

谢谢

他们是你思考这个问题的方式,我觉得 JavaScript 很喜欢。您想要通过复制所有属性来创建深拷贝。然而,Xamarin 对象对于这样的事情来说太复杂了(即使你可以进行深度复制,例如绑定也无法进行简单复制)。

因此,与其制作单个 Grid 对象并尝试创建它的副本,另一种看待它的方式是 "I want to define a template, and then create multiple instances according to that template"。为此,Xamarin 具有 DataTemplate class,这使我们能够在 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 而不是仅仅指向一个对象然后说获取副本。另请记住,DataTemplateViewx:Name 无法在页面后面的代码中访问,但不需要良好的 Xamarin 设置。好处是它可以工作,完成可能的绑定,所以你可以在你的网格中定义一个 Label 像这样:

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

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

希望这对您有所帮助