将附加属性复制到 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
而不是仅仅指向一个对象然后说获取副本。另请记住,DataTemplate
中 View
的 x:Name
无法在页面后面的代码中访问,但不需要良好的 Xamarin 设置。好处是它可以工作,完成可能的绑定,所以你可以在你的网格中定义一个 Label
像这样:
<Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0"></Label>
然后,如果您的模板化 Grid
不同 BindingContext
,则可以为每个实例提供不同的数据以将不同的数据绑定到它的视图。
希望这对您有所帮助
我正在创建具有如下两个标签的网格对象的新实例。
<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
而不是仅仅指向一个对象然后说获取副本。另请记住,DataTemplate
中 View
的 x:Name
无法在页面后面的代码中访问,但不需要良好的 Xamarin 设置。好处是它可以工作,完成可能的绑定,所以你可以在你的网格中定义一个 Label
像这样:
<Label Text="{Binding Name}" Grid.Column="0" Grid.Row="0"></Label>
然后,如果您的模板化 Grid
不同 BindingContext
,则可以为每个实例提供不同的数据以将不同的数据绑定到它的视图。
希望这对您有所帮助