我正在尝试制作更好的解决方案架构,为此我将代码的许多部分分离在不同的文件中。因为我的应用程序使用大量数据模板,所以我将它们推送到不同的 ResourceDictionary.xaml 文件中。
问题:
我有一个视图Agenda.xaml,视图模型AgendaViewModel。此视图具有一个列表视图,该视图在外部资源字典文件中调用其数据模板。但是,如果我想在 dataTemplate 中放置一个绑定命令,则该命令永远不会执行,因为(我猜(资源字典在哪里我的数据模板没有引用 ViewModel。
我能做什么?
我已经尝试了一些奇怪的绑定代码,例如
<TapGestureRecognizer Command="{Binding BindingContext.OpenActiviteCommand, Source={x:Reference agendaPage}}" CommandParameter="{Binding .}"/>
其中"agendaPage"是 x:Agenda.xaml 的名称。
我在谷歌上找到的只是关于 WPF 和绑定属性,在 Xamarin 窗体上不可用(RelativeSource、ElementName 等...(
我知道我可以把dataTemplate放在我的Agenda.xaml视图中,但我真的想把它保存在一个外部文件中。我想避免查看 1500 行的文件....
这是我的议程.xaml 视图
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Corim.Portable.CorimTouch.ViewForms.Agenda.AgendaViewDetail"
xmlns:converters="clr-namespace:Corim.Portable.CorimTouch.Converters"
Title="Agenda"
x:Name="agendaPage">
<ContentPage.Content>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="{StaticResource LightGrayCorim}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Liste itv,pointage,activite -->
<ListView
x:Name="listAgenda"
Grid.Row="1"
SeparatorVisibility="None"
HasUnevenRows="True"
SelectionMode="None"
CachingStrategy="RecycleElement"
ItemsSource="{Binding AgendaList}"
ItemTemplate="{StaticResource agendaTemplateSelector}"
BackgroundColor="{StaticResource LightGrayCorim}">
</ListView>
</Grid>
</ContentPage.Content>
</ContentPage>
这是 AgendaTemplates.xaml 中 Datatemplate 的一部分
。<DataTemplate x:Key="agenda-adresse-intervention">
<ViewCell>
<Frame Margin="10,5,10,0" HasShadow="False" Padding="0" CornerRadius="10" IsClippedToBounds="True">
<controls:CustomTappedStackLayout
BackgroundColor="White"
TappedBackgroundColor="{StaticResource RollOver}"
HorizontalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="10">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.OpenParcCommand, Source={x:Reference agendaPage}}" CommandParameter="{Binding .}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image
Source="localisation_adresse"
WidthRequest="30"
HeightRequest="30"
Aspect="AspectFit"
HorizontalOptions="Start"
Margin="10"
VerticalOptions="StartAndExpand"/>
<StackLayout
HorizontalOptions="FillAndExpand"
Orientation="Vertical">
<Label
Text="{Binding Client}"
IsVisible="{Binding Client, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource SemiBoldFont}"
FontSize="{StaticResource MediumTextSize}"
TextColor="Black"/>
<Label
Text="{Binding Title}"
IsVisible="{Binding Title, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource RegularFont}"
FontSize="{StaticResource DefaultTextSize}"
TextColor="Gray"/>
</StackLayout>
</controls:CustomTappedStackLayout>
</Frame>
</ViewCell>
</DataTemplate>
但是如果我想在dataTemplate中放置一个绑定命令,命令 永远不会执行,因为(我猜(资源字典在哪里 我的数据模板未引用视图模型。
你猜错了:做你正在做的事情是完全可以的,应该透明地工作。绑定在运行时解析,您的数据模板不知道将绑定的对象的任何信息。
第一:放弃BindingContext.OpenActiviteCommand
废话:)只需绑定到OpenActiviteCommand
,唯一的问题是:
第二:你的OpenActiviteCommand
在哪里?
AgendaTemplates
的数据上下文是AgendaList
中的项目。 如果AgendaList
的类型是ObservableCollection<AgendaViewModel>
,并且您的AgendaViewModel
有OpenParcCommand
那么应该没问题:
public class AgendaViewModel
{
public AgendaViewModel(ICommand openParcCommand)
{
OpenParcCommand = openParcCommand;
}
public ICommand OpenParcCommand { get; }
}
在你的AgendaPageViewModel
:
public class AgendaPageViewModel
{
public ObservableCollection<AgendaViewModel> AgendaList { get; }
}
感谢@Roubachof
解决方案被AgendaDataViewModel的ListView取代了我的干预模型列表视图。
AgendaViewModel是一个新类,它包含我需要的所有命令和一个干预模型。
这是议程数据视图模型:
public class AgendaDataViewModel : HybridContentViewModel
{
private InterventionModel _model;
public InterventionModel Model
{
get => _model;
set { _model = value; }
}
public ICommand OpenActiviteCommand { get; private set; }
public AgendaDataViewModel()
{
this.OpenActiviteCommand = new Command<InterventionModel>(this.OpenActivite);
}
/// <summary>
/// Ouvre le formulaire d'édition de l'activité
/// </summary>
/// <param name="model"></param>
private void OpenActivite(InterventionModel model)
{
//TODO amener sur le formulaire d'activité
}
}
我的议程模板.xaml
<!--Template pour l'affichage du parc-->
<DataTemplate x:Key="agenda-adresse-intervention">
<ViewCell>
<Frame Margin="10,5,10,0" HasShadow="False" Padding="0" CornerRadius="10" IsClippedToBounds="True">
<controls:CustomTappedStackLayout
BackgroundColor="White"
TappedBackgroundColor="{StaticResource RollOver}"
HorizontalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="10">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OpenParcCommand}" CommandParameter="{Binding Model}" NumberOfTapsRequired="1"/>
</StackLayout.GestureRecognizers>
<Image
Source="localisation_adresse"
WidthRequest="30"
HeightRequest="30"
Aspect="AspectFit"
HorizontalOptions="Start"
Margin="10"
VerticalOptions="StartAndExpand"/>
<StackLayout
HorizontalOptions="FillAndExpand"
Orientation="Vertical">
<Label
Text="{Binding Model.Client}"
IsVisible="{Binding Model.Client, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource SemiBoldFont}"
FontSize="{StaticResource MediumTextSize}"
TextColor="Black"/>
<Label
Text="{Binding Model.Title}"
IsVisible="{Binding Model.Title, Converter={StaticResource StringEmptyBooleanConverter}}"
FontFamily="{StaticResource RegularFont}"
FontSize="{StaticResource DefaultTextSize}"
TextColor="Gray"/>
</StackLayout>
</controls:CustomTappedStackLayout>
</Frame>
</ViewCell>
</DataTemplate>
如您所见,值绑定由以下行进行:
{Binding Model.Client}
其中客户端是绑定属性的名称。要绑定命令,您不需要 Model,只需像这样绑定:
Command={Binding CommandName}
希望将来对某人有所帮助!