Xaml 在资源文件中定义listview,可以在同一模型的不同位置使用

Xaml 在资源文件中定义listview,可以在同一模型的不同位置使用,xaml,xamarin,xamarin.forms,Xaml,Xamarin,Xamarin.forms,我创建了以下ListView来显示数据 <dataControls:RadListView x:Name="ItemsListView" ItemsSource="{Binding StudyResults,Mode=TwoWay}" MinimumHeightRequest="70"

我创建了以下ListView来显示数据

<dataControls:RadListView x:Name="ItemsListView" 
                                      ItemsSource="{Binding StudyResults,Mode=TwoWay}"
                                      MinimumHeightRequest="70"
                                      HeightRequest="{Binding Height}"
                                      SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
                <dataControls:RadListView.ItemTemplate>
                    <DataTemplate>
                        <listView:ListViewTemplateCell>
                            <listView:ListViewTemplateCell.View>
                                <Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
                                    <StackLayout Padding="5,1,1,5" Grid.Column="0">
                                        <Grid >
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width="Auto"/>
                                            </Grid.ColumnDefinitions>
                                            <maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
                                        </Grid>
                                        <StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
                                            <BoxView Margin="0"
                                                     BackgroundColor="Gray"
                                                     HeightRequest=".25" />
                                            <Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
                                            <BoxView Margin="0"
                                                     BackgroundColor="Gray"
                                                     HeightRequest=".25" />
                                        </StackLayout>
                                    </StackLayout>
                                </Grid>
                            </listView:ListViewTemplateCell.View>
                        </listView:ListViewTemplateCell>
                    </DataTemplate>
                </dataControls:RadListView.ItemTemplate>
            </dataControls:RadListView>

我想在其他屏幕/视图中重复使用这个完全相同的ListView+标记,只是使用不同的ItemsSource,它将绑定到同一个模型。我需要在不同的屏幕中使用不同的项目源


有没有更好的方法来创建某种类型的资源,以便我可以重用它?

您可以将
DataTemplate
设置为资源,这会起作用。

您可以将
DataTemplate
设置为资源,这会起作用。

根据lvan的意见,您可以在ContentPage中设置DataTemplate。resource或ResourceDictionary,一些代码如下:

<ContentPage.Resources>

    <DataTemplate x:Key="Radtemplate">
        <listView:ListViewTemplateCell>
            <listView:ListViewTemplateCell.View>
                <Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
                    <StackLayout Padding="5,1,1,5" Grid.Column="0">
                        <Grid >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
                        </Grid>
                        <StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
                            <BoxView Margin="0"
                                                 BackgroundColor="Gray"
                                                 HeightRequest=".25" />
                            <Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
                            <BoxView Margin="0"
                                                 BackgroundColor="Gray"
                                                 HeightRequest=".25" />
                        </StackLayout>
                    </StackLayout>
                </Grid>
            </listView:ListViewTemplateCell.View>
        </listView:ListViewTemplateCell>
    </DataTemplate>
</ContentPage.Resources>

<StackLayout>
    <!--  Place new controls here  -->

    <dataControls:RadListView x:Name="ItemsListView" ItemTemplate="{StaticResource Radtemplate}"
                                  ItemsSource="{Binding StudyResults,Mode=TwoWay}"
                                  MinimumHeightRequest="70"
                                  HeightRequest="{Binding Height}"
                                  SelectedItem="{Binding SelectedItem,Mode=TwoWay}">

    </dataControls:RadListView>
</StackLayout>

关于DateTemplate详细信息,您可以查看以下文章:

更新: 因为RadListView是第三方控件,所以我无法安装它,所以我使用ListView作为示例,它是相同的,您可以看看如何使用TapGestureRecognizer

请先为页面指定一个x:name=listviewpage,然后

<ContentPage
x:Class="demo3.listviewsample.Page2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="listviewpage"
mc:Ignorable="d">
<ContentPage.Resources>
    <DataTemplate x:Key="datatemplate1">
        <ViewCell>
            <StackLayout Margin="5" VerticalOptions="FillAndExpand">
                <BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
                <Label Text="{Binding username}">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding BindingContext.command, Source={x:Reference listviewpage}}" CommandParameter="{Binding Email}" />
                    </Label.GestureRecognizers>
                </Label>
            </StackLayout>
        </ViewCell>
    </DataTemplate>
</ContentPage.Resources>
<ContentPage.Content>
    <StackLayout>
        <ListView
            HasUnevenRows="True"
            ItemTemplate="{StaticResource datatemplate1}"
            ItemsSource="{Binding models}" />
    </StackLayout>
</ContentPage.Content>

或者,您可以先给ViewCell一个x:Name viewcell1,然后:

<ContentPage.Resources>
    <DataTemplate x:Key="datatemplate1">
        <ViewCell x:Name="viewcell">
            <StackLayout Margin="5" VerticalOptions="FillAndExpand">
                <BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
                <Label Text="{Binding username}">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding Parent.BindingContext.command, Source={x:Reference viewcell}}" CommandParameter="{Binding Email}" />
                    </Label.GestureRecognizers>
                </Label>
            </StackLayout>
        </ViewCell>
    </DataTemplate>
</ContentPage.Resources>

 public partial class Page2 : ContentPage
{
    public ObservableCollection<model3> models { get; set; }
    public RelayCommand1 command { get; set; }
    public Page2()
    {
        InitializeComponent();
        models = new ObservableCollection<model3>()
        {
            new model3(){username="cherry",Email="cherry@outlook.com"},
            new model3(){username="barry",Email="barry@outlook.com"}
        };
        command = new RelayCommand1(obj => method1((string)obj));
        this.BindingContext = this;       
    }

    private void method1(string str)
    {
        Console.WriteLine("the email is {0}",str);
    }
}
public class model3
{
    public string username { get; set; }
    public string Email { get; set; }
}

公共部分类第2页:内容页
{
公共可观测集合模型{get;set;}
公共RelayCommand1命令{get;set;}
公共页2()
{
初始化组件();
模型=新的ObservableCollection()
{
新模型3(){username=“cherry”,电子邮件=”cherry@outlook.com"},
新模型3(){username=“barry”,Email=”barry@outlook.com"}
};
command=newrelaycommand1(obj=>method1((字符串)obj));
this.BindingContext=this;
}
私有void方法1(字符串str)
{
WriteLine(“电子邮件是{0}”,str);
}
}
公共类模型3
{
公共字符串用户名{get;set;}
公共字符串电子邮件{get;set;}
}
以下是继承ICommand的命令:

public class RelayCommand1 : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public RelayCommand1(Action<object> execute)
        : this(execute, null)
    {
    }

    public RelayCommand1(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged;


    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}
公共类RelayCommand1:ICommand
{
私有只读谓词_canExecute;
私有只读操作\u执行;
公共中继命令1(操作执行)
:此(执行,空)
{
}
公共RelayCommand1(操作执行,谓词canExecute)
{
_执行=执行;
_canExecute=canExecute;
}
公共布尔CanExecute(对象参数)
{
返回_canExecute==null?true:_canExecute(参数);
}
公共事件处理程序CanExecuteChanged;
public void Execute(对象参数)
{
_执行(参数);
}
}

当我点击label时,它工作正常。

根据lvan的意见,您可以在ContentPage.Resource或ResourceDictionary中设置DataTemplate,一些代码如下:

<ContentPage.Resources>

    <DataTemplate x:Key="Radtemplate">
        <listView:ListViewTemplateCell>
            <listView:ListViewTemplateCell.View>
                <Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
                    <StackLayout Padding="5,1,1,5" Grid.Column="0">
                        <Grid >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
                        </Grid>
                        <StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
                            <BoxView Margin="0"
                                                 BackgroundColor="Gray"
                                                 HeightRequest=".25" />
                            <Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
                            <BoxView Margin="0"
                                                 BackgroundColor="Gray"
                                                 HeightRequest=".25" />
                        </StackLayout>
                    </StackLayout>
                </Grid>
            </listView:ListViewTemplateCell.View>
        </listView:ListViewTemplateCell>
    </DataTemplate>
</ContentPage.Resources>

<StackLayout>
    <!--  Place new controls here  -->

    <dataControls:RadListView x:Name="ItemsListView" ItemTemplate="{StaticResource Radtemplate}"
                                  ItemsSource="{Binding StudyResults,Mode=TwoWay}"
                                  MinimumHeightRequest="70"
                                  HeightRequest="{Binding Height}"
                                  SelectedItem="{Binding SelectedItem,Mode=TwoWay}">

    </dataControls:RadListView>
</StackLayout>

关于DateTemplate详细信息,您可以查看以下文章:

更新: 因为RadListView是第三方控件,所以我无法安装它,所以我使用ListView作为示例,它是相同的,您可以看看如何使用TapGestureRecognizer

请先为页面指定一个x:name=listviewpage,然后

<ContentPage
x:Class="demo3.listviewsample.Page2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="listviewpage"
mc:Ignorable="d">
<ContentPage.Resources>
    <DataTemplate x:Key="datatemplate1">
        <ViewCell>
            <StackLayout Margin="5" VerticalOptions="FillAndExpand">
                <BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
                <Label Text="{Binding username}">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding BindingContext.command, Source={x:Reference listviewpage}}" CommandParameter="{Binding Email}" />
                    </Label.GestureRecognizers>
                </Label>
            </StackLayout>
        </ViewCell>
    </DataTemplate>
</ContentPage.Resources>
<ContentPage.Content>
    <StackLayout>
        <ListView
            HasUnevenRows="True"
            ItemTemplate="{StaticResource datatemplate1}"
            ItemsSource="{Binding models}" />
    </StackLayout>
</ContentPage.Content>

或者,您可以先给ViewCell一个x:Name viewcell1,然后:

<ContentPage.Resources>
    <DataTemplate x:Key="datatemplate1">
        <ViewCell x:Name="viewcell">
            <StackLayout Margin="5" VerticalOptions="FillAndExpand">
                <BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
                <Label Text="{Binding username}">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding Parent.BindingContext.command, Source={x:Reference viewcell}}" CommandParameter="{Binding Email}" />
                    </Label.GestureRecognizers>
                </Label>
            </StackLayout>
        </ViewCell>
    </DataTemplate>
</ContentPage.Resources>

 public partial class Page2 : ContentPage
{
    public ObservableCollection<model3> models { get; set; }
    public RelayCommand1 command { get; set; }
    public Page2()
    {
        InitializeComponent();
        models = new ObservableCollection<model3>()
        {
            new model3(){username="cherry",Email="cherry@outlook.com"},
            new model3(){username="barry",Email="barry@outlook.com"}
        };
        command = new RelayCommand1(obj => method1((string)obj));
        this.BindingContext = this;       
    }

    private void method1(string str)
    {
        Console.WriteLine("the email is {0}",str);
    }
}
public class model3
{
    public string username { get; set; }
    public string Email { get; set; }
}

公共部分类第2页:内容页
{
公共可观测集合模型{get;set;}
公共RelayCommand1命令{get;set;}
公共页2()
{
初始化组件();
模型