Xamarin显示来自DataTemplate的一项



我想显示一个项目与DataTemplate在我的Xamarin应用程序,我可以使用什么XAML控件?

在我的情况下,我正在建立一个会议应用程序,我正试图显示会议的所有者。
我尝试使用CollectionView (UserTemplate是一个DataTemplate):

<CollectionView
ItemsSource="{Binding Meeting.Owner}"
ItemTemplate="{StaticResource UserTemplate}"/>

,但这并没有显示任何东西,因为CollectionView只支持项目列表(当我试图使用列表时,它真的很有效)。
对于单个条目,我可以使用什么替代方案?

UserTemplate XAML:

<DataTemplate x:Key="UserTemplate">
<Grid Padding="10"
RowDefinitions="Auto,Auto"
ColumnDefinitions="Auto,Auto">
<Image Grid.RowSpan="2" 
Source="{Binding IconURL}" 
Aspect="AspectFill"
HeightRequest="60" 
WidthRequest="60" />
<Label Grid.Column="1" 
Text="{Binding Name}" 
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1" 
Text="{Binding age}"
FontAttributes="Italic" 
VerticalOptions="End" />
</Grid>
</DataTemplate>

我知道这可能不是一个完美的解决方案,但它可能会帮助你。

你可以用ContentView代替Template来显示你的数据。它的XML看起来几乎与您的模板相似。

XAML:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
xmlns:models="clr-namespace:TestAppNew.Models"
x:Class="TestAppNew.Views.UserView"
x:Name="View">
<Frame BindingContext="{Binding Source={x:Reference View}, Path=User}" 
x:DataType="models:User">
<Grid Padding="10"
RowDefinitions="Auto,Auto"
ColumnDefinitions="Auto,Auto">
<Label Grid.Column="1" 
Text="{Binding Name}" 
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1" 
Text="{Binding age}"
FontAttributes="Italic" 
VerticalOptions="End" />
</Grid>
</Frame>
</ContentView>

背后的代码:

public partial class UserView : ContentView
{
public User User
{
get => (User)GetValue(UserProperty);
set => SetValue(UserProperty, value);
}
public static readonly BindableProperty UserProperty =
BindableProperty.Create("User", typeof(User), typeof(UserView), new User());
public UserView()
{
InitializeComponent();
}
}

现在你可以在代码中使用这个视图了。

单项目:

<views:UserView User="{Binding Meeting.Owner}" />

或多个:

<CollectionView ItemsSource="{Binding Meetings}">
<CollectionView.ItemTemplate>
<DataTemplate>
<views:UserView User="{Binding Owner}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

不做进一步的研究,我认为你应该能够包装这个视图在一个额外的DataTemplate,这样你仍然可以访问ListView或CollectionView的直接ItemTemplate属性

给定一个包含属性UserMeeting,如何显示Meeting.UserDataTemplate?

要使用CollectionView,我们需要一个List<User>。一种解决方案是创建一个"值转换器":

using System;
using System.Collections.Generic;
using System.Globalization;
using Xamarin.Forms;
namespace BindSubView
{
/// <summary>
/// Given a single object, return a list containing just that object.
/// </summary>
public class OneItemListConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new List<object> { value };
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

使用例子:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BindSubView"
x:Class="BindSubView.MainPage">
<ContentPage.BindingContext>
<local:MainPageViewModel/>
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<local:OneItemListConverter x:Key="oneItemList" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<CollectionView ItemsSource="{Binding Meeting.User, Converter={StaticResource oneItemList}}" HeightRequest="100">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}"/>
<Label Text="{Binding SomeProperty}"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>

我已经展示了一个内联的DataTemplate,但是它可以使用在其他地方定义的DataTemplate:

<CollectionView ... ItemTemplate="{StaticResource YourTemplateName}"/>

上面的答案使用了MainPageViewModelMeetingUser的定义,如下所示。


OR如果目标是在另一个属性(Meeting)上显示属性(User)的详细信息,可能根本不需要DataTemplate。

这是一个不同于所问问题的目标;这展示了如何引用"嵌套的"。如"meeting . user . name"等属性

考虑这些模型:

using Xamarin.Forms;
namespace BindSubView
{
public class Meeting : BindableObject
{
public string Description { get; set; } = "Description of meeting";
public User User { get; set; } = new User();
}
public class User : BindableObject
{
public string Name { get; set; } = "Test User";
public string SomeProperty { get; set; } = "Test SomeProperty";
}
}

: BindableObject是可选的;它是为了方便方法OnPropertyChanged(nameof(SomeProperty));

的使用(在以后的开发中)。这个视图模型:

public class MainPageViewModel : BindableObject
{
public Meeting Meeting { get; set; } = new Meeting();
}

两种可能的方法。

1。直接参考"嵌套"。属性。例:{Binding Meeting.User.Name}:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BindSubView"
x:Class="BindSubView.MainPage">
<ContentPage.BindingContext>
<local:MainPageViewModel/>
</ContentPage.BindingContext>
<StackLayout>
<Label Text="{Binding Meeting.Description}"/>
<StackLayout>
<Label Text="{Binding Meeting.User.Name}"/>
<Label Text="{Binding Meeting.User.SomeProperty}"/>
</StackLayout>
</StackLayout>
</ContentPage>

或2。设置一个不同的& indingcontext ">

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BindSubView"
x:Class="BindSubView.MainPage">
<ContentPage.BindingContext>
<local:MainPageViewModel/>
</ContentPage.BindingContext>
<!-- "Meeting" refers to a Property on the enclosing BindingContext. Here it means "MainPageViewModel.Meeting". -->
<StackLayout BindingContext="{Binding Meeting}">
<Label Text="{Binding Description}"/>
<!-- "User" refers to a Property on the enclosing BindingContext. Here it means "MainPageViewModel.Meeting.User". -->
<StackLayout BindingContext="{Binding User}">
<Label Text="{Binding Name}"/>
<Label Text="{Binding SomeProperty}"/>
</StackLayout>
</StackLayout>
</ContentPage>

这两个XAML代码段的行为相同。都显示:

Description of meeting
Test User
Test SomeProperty