【问题标题】:How bind a command in DataTemplate in Resource Dictionary?如何在资源字典的 DataTemplate 中绑定命令?
【发布时间】:2019-12-14 04:38:02
【问题描述】:

我正在尝试创建一个更好的解决方案架构,因为我已将许多代码部分分隔在不同的文件中。因为我的应用程序使用了很多 DataTemplate,所以我将它们推送到不同的 ResourceDictionary.xaml 文件中。

问题:

我有一个带有 viewModel AgendaViewModel 的视图 Agenda.xaml。此视图有一个 ListView,它调用外部 ResourceDictionary 文件中的数据模板。但是,如果我想在 dataTemplate 中放置一个绑定命令,则该命令永远不会执行,因为(我猜)我的 DataTemplate 所在的资源字典没有引用 ViewModel。

我能做什么?

我已经尝试过一些奇怪的绑定代码,比如

<TapGestureRecognizer Command="{Binding BindingContext.OpenActiviteCommand, Source={x:Reference agendaPage}}" CommandParameter="{Binding .}"/>

“agendaPage”是 Agenda.xaml 的 x:Name。

我在 Google 上找到的只是 WPF 和 Xamarin 表单上不可用的 Binding 属性(RelativeSource、ElementName 等...)

我知道我可以将 dataTemplate 放在我的 Agenda.xaml 视图中,但我真的想将它保存在外部文件中。我想避免查看 1500 行的文件....

这是我的 Agenda.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 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>

【问题讨论】:

    标签: xaml xamarin.forms binding viewmodel datatemplate


    【解决方案1】:

    但是如果我想在 dataTemplate 中放置一个绑定命令,命令 永远不会执行,因为(我猜)资源字典在哪里 我的 DataTemplate 没有引用 ViewModel。

    你猜错了:做你正在做的事情完全没问题,并且应该透明地工作。绑定在运行时解析,您的数据模板对将要绑定的对象一无所知。

    第一个:放弃BindingContext.OpenActiviteCommand 废话:) 绑定到OpenActiviteCommand,唯一的问题是:

    第二个:你的OpenActiviteCommand在哪里?

    AgendaTemplates 的数据上下文是AgendaList 中的项目。 如果AgendaList 的类型是ObservableCollection&lt;AgendaViewModel&gt;,而你的AgendaViewModelOpenParcCommand,那么应该没问题:

    public class AgendaViewModel
    {
        public AgendaViewModel(ICommand openParcCommand)
        {
            OpenParcCommand = openParcCommand;
        }
    
        public ICommand OpenParcCommand { get; }
    }
    

    在你的AgendaPageViewModel:

    public class AgendaPageViewModel
    {
        public ObservableCollection<AgendaViewModel> AgendaList { get; }
    }
    

    【讨论】:

    • 感谢您的帮助;你的解决方案对我来说似乎很好。试一试后我会回来找你的!
    【解决方案2】:

    感谢@Roubachof

    解决办法是用 AgendaDataViewModel 的 ListView 替换我的 InterventionModel 的 ListView。

    AgendaViewModel 是一个新类,其中包含我需要的所有命令和一个 InterventionModel。

    这是 AgendaDataViewModel :

    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é
            }
        }
    

    我的 AgendaTemplate.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}
    

    其中 Client 是绑定属性的名称。并且要绑定命令,您不需要模型,只需像这样绑定:

    Command={Binding CommandName}
    

    希望它对未来的人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 2012-11-10
      • 2011-07-21
      • 2012-09-03
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      相关资源
      最近更新 更多