Поведение.Команда Forms не выполняется

#c# #xamarin #xamarin.forms

#c# #xamarin #xamarin.forms

Вопрос:

Я пытаюсь обновить существующий проект Xamarin до последних версий различных библиотек. Сами формы Xamarin находятся в общей библиотеке. На моей странице есть ListView, и я пытаюсь зафиксировать событие, вызванное, когда элемент «выбран». Однако команда ICommand в моей ViewModel не выполняется.

Примечания:

  • Я использую Xamarin.Формы 4.8 … но пришлось понизить поведение.Формы до 1.3, потому что код находится в стандартной библиотеке .NET.
  • Если я перейду на поведение.Формы 1.4 возникает ошибка времени разработки (см. Фото ниже)

ИНФОРМАЦИЯ ОБ ОБЩЕЙ БИБЛИОТЕКЕ:
.NET Standard 2.0

  • Acr.UserDialogs Version=»7.1.0.454″
  • AzureMobileClient.Версия помощников =»4.0.2.507-pre»
  • Поведение.Версия Forms =»1.3.0″
  • Com.Airbnb.Xamarin.Формы.Версия Лотти=»3.1.3″
  • Призма.DryIoc.Версия Forms=»8.0.0.1850-pre»
  • Призма.Версия Forms=»8.0.0.1850-pre»
  • Refractor.MvvmHelpers Version=»1.6.2″
  • Telerik.UI.for.Xamarin.Общая версия =»2020.2.624.1″
  • Telerik.UI.for.Xamarin.Версия DataControls=»2020.2.624.1″
  • Telerik.UI.for.Xamarin.Версия DataGrid=»2020.2.624.1″
  • Telerik.UI.for.Xamarin.Версия примитивов=»2020.2.624.1″
  • Версия Telerik.UI.for.Xamarin.SkiaSharp=»2020.2.624.1″
  • Xamarin.Загрузка FFImageLoading.Версия Forms =»2.4.11.982″
  • Xamarin.Версия FFImageLoading.Svg.Forms=»2.4.11.982″
  • Xamarin.Загрузка FFImageLoading.Версия преобразований=»2.4.11.982″
  • Xamarin.Версия Forms =»4.8.0.1364″

КЛАСС ПРЕОБРАЗОВАТЕЛЯ:
Исходный программист возвращает ‘ItemTapped’ EventArgs…

 public class SelectedItemEventArgsConverter : IValueConverter
{
    #region <Methods>

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var eventArgs = value as ItemTappedEventArgs;
        return eventArgs != null ? eventArgs.Item : null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    } 

    #endregion
}
  

ПРОСМОТР МОДЕЛИ:
ListView связывает и отображает элементы (см. Фото ниже)…

 using CustomControls;
using Models;
using MvvmHelpers.Commands;
using Prism.Navigation;
using Prism.Services;
using System.Collections.Generic;

public class MainPageViewModel : ViewModelBase
{
    #region Constructors

    public MainPageViewModel(INavigationService navigationService, IPageDialogService pageDialogService, IDeviceService deviceService) : base(navigationService, pageDialogService, deviceService)
    {
        Initialize();
    }

    #endregion

    #region <Properties>

    public AccordionNode ShakeoutListItemsAccordion { get; private set; }

    public Command<SimpleListItem> OnShakeoutListItemSelectedCommand { get; private set; }

    public List<SimpleListItem> ShakeoutListItems { get; private set; } = new List<SimpleListItem>();

    #endregion

    #region <Events>

    public async void OnShakeoutListItemSelected(SimpleListItem item)
    {
        if (item.Name == "Add Shakeout")
            await NavigationService.NavigateAsync("ShakeoutDocumentGeneratorPage");
    }

    #endregion

    private void Initialize()
    {
        // Commands
        OnShakeoutListItemSelectedCommand = new Command<SimpleListItem>(OnShakeoutListItemSelected);

        // Accordians
        ShakeoutListItemsAccordion = new AccordionNode("OverwrittenInView", GlobalVariables.Accordion.Height, GlobalVariables.Accordion.HeaderBackgroundColor, GlobalVariables.Accordion.HeaderColorTextColor, GlobalVariables.Accordion.SeparatorColor);

        // Data
        ShakeoutListItems.Add(new SimpleListItem { Name = "Add Shakeout", Title = string.Empty, Type = string.Empty });
    }
}
  

Вид:
Поскольку происходит событие ‘ItemTapped’ класса конвертера, я фокусируюсь на этом событии … но я могу изменить это (при необходимости)

 <?xml version="1.0" encoding="utf-8" ?>
<views:BaseContentPage 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"
             mc:Ignorable="d"
             xmlns:behaviors="clr-namespace:Behaviors;assembly=Behaviors"
             xmlns:forms="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
             xmlns:converters="clr-namespace:ETC.Operations.Pulse.Mobile.Converters;assembly=ETC.Operations.Pulse.Mobile"
             xmlns:customControls="clr-namespace:ETC.Operations.Pulse.Mobile.CustomControls;assembly=ETC.Operations.Pulse.Mobile"
             xmlns:helpers="clr-namespace:ETC.Operations.Pulse.Mobile.Helpers;assembly=ETC.Operations.Pulse.Mobile"
             xmlns:views="clr-namespace:ETC.Operations.Pulse.Mobile.Views;assembly=ETC.Operations.Pulse.Mobile"
             x:Class="ETC.Operations.Pulse.Mobile.MainPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <converters:SelectedItemEventArgsConverter x:Key="EventToCommand"/>
            <forms:SvgImageSourceConverter x:Key="SvgImageSourceConverter"></forms:SvgImageSourceConverter>
        </ResourceDictionary>
    </ContentPage.Resources>

    <ContentPage.Content>
        <ScrollView  VerticalOptions="FillAndExpand" Padding="10">
            <StackLayout Spacing="0" Padding="0">

                <!-- SHAKEOUTS -->
                <StackLayout Spacing="0" Padding="0"  Style="{DynamicResource AccordionTitleStyle}">
                    <StackLayout Style="{DynamicResource AccordionHeaderStackLayoutStyle}">
                        <StackLayout.GestureRecognizers>
                            <TapGestureRecognizer Command="{Binding ShakeoutListItemsAccordion.ExpandContractAccordion}"/>
                        </StackLayout.GestureRecognizers>
                        <Label Text="Shakeouts" Style="{DynamicResource AccordionHeaderTextStyle}" VerticalTextAlignment="Center"/>
                        <Label TextColor="{Binding ShakeoutListItemsAccordion.HeaderTextColor}"  HorizontalOptions="EndAndExpand" Text="{Binding ShakeoutListItemsAccordion.IconText}" VerticalTextAlignment="Center"/>
                    </StackLayout>
                    <BoxView HeightRequest="1" Color="{Binding ShakeoutListItemsAccordion.LineColor}" HorizontalOptions="FillAndExpand"></BoxView>
                </StackLayout>

                <!-- SHAKEOUTS: Controls -->
                <StackLayout BackgroundColor="{DynamicResource BackgroundColor}" HeightRequest="200" IsVisible="{Binding ShakeoutListItemsAccordion.IsExpanded}" Padding="0" Spacing="0">
                    <ListView
                        x:Name="lvShakeoutListItems"
                        HorizontalOptions="FillAndExpand"
                        VerticalOptions="FillAndExpand"
                        ItemsSource="{Binding ShakeoutListItems}"
                        RowHeight="40">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <Grid Style="{DynamicResource ListViewGridItemStyle}" RowSpacing="0" ColumnSpacing="0" Margin="13,0,0,0">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="0.8*" />
                                            <ColumnDefinition Width="150" />
                                        </Grid.ColumnDefinitions>

                                        <Label Grid.Row="0" Grid.Column="0"  Text="{Binding Name}" Style="{DynamicResource ListViewLabelCenterRowLeft}" TextColor="{StaticResource LabelValueTextColor}" Margin="0,10,0,0"/>
                                    </Grid>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                        <ListView.Behaviors>
                            <behaviors:EventHandlerBehavior EventName="ItemTapped">
                                <behaviors:InvokeCommandAction Command="{Binding OnShakeoutListItemSelectedCommand}" Converter="{StaticResource EventToCommand}" />
                            </behaviors:EventHandlerBehavior>
                        </ListView.Behaviors>
                    </ListView>
                </StackLayout>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</views:BaseContentPage>
  

ИЗОБРАЖЕНИЯ ТЕЛЕФОНА:
Как вы можете видеть … ViewModel привязывается к данным.

введите описание изображения здесь

ПРИМЕЧАНИЯ:
Обновление до поведения.Forms 1.4 генерирует ошибку времени разработки.

введите описание изображения здесь

Обновления:
Вот мои обновления по предложениям, внесенным участниками…

  • Опция «Жест касания к основному объекту ячейки» не запускает событие (вообще)
  • Возникает событие «Выбранный элемент»…но не вызывает событие «MainPageViewModel OnShakeoutListItemSelected»
  • В настоящее время я изучаю «Поведение Corcav» в NuGet

Комментарии:

1. Я тестирую предоставленный вами код и воспроизводю ошибку. Для поведения. В формах 1.4 сообщалось об этой проблеме, и теперь она не будет исправлена. Вы можете перейти по ссылке ниже или открыть новый выпуск на GitHub. github.com/davidbritch/behaviors/issues/22 Пожалуйста, используйте Правила поведения. Вместо этого формирует 1.3.

2. @WendyZang-MSFT Я использую поведение. Формы 1.3

Ответ №1:

Вариант 1: используйте жест касания для основного объекта ячейки

 <ListView
                        x:Name="lvShakeoutListItems"
                        HorizontalOptions="FillAndExpand"
                        VerticalOptions="FillAndExpand"
                        ItemsSource="{Binding ShakeoutListItems}"
                        RowHeight="40">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Style="{DynamicResource ListViewGridItemStyle}" RowSpacing="0" ColumnSpacing="0" Margin="13,0,0,0">
                            **<Grid.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding OnShakeoutListItemSelectedCommand}" CommandParameter="{Binding .}"/>
                            </Grid.GestureRecognizers>**
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="0.8*" />
                                <ColumnDefinition Width="150" />
                            </Grid.ColumnDefinitions>

                            <Label Grid.Row="0" Grid.Column="0"  Text="{Binding Name}" Style="{DynamicResource ListViewLabelCenterRowLeft}" TextColor="{StaticResource LabelValueTextColor}" Margin="0,10,0,0"/>
                        </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

  

Вариант 2: использовать выбранный элемент для основного объекта ячейки

 <ListView
                        x:Name="lvShakeoutListItems"
                        HorizontalOptions="FillAndExpand"
                        VerticalOptions="FillAndExpand"
                        ItemsSource="{Binding ShakeoutListItems}"
            SelectedItem="{Binding SelctedItem}"
                        RowHeight="40">
...
</>

  

Вариант 3: используйте corcav behavior nuget, чтобы получить событие для управления поведением

Комментарии:

1. Пожалуйста, ознакомьтесь с ОБНОВЛЕНИЯМИ SECTIO0N, которые я добавил к своему вопросу (выше)

2. для варианта 1 : событие запускается (я думаю), но из-за BindingContext оно не фиксируется, попробуйте использовать in code behind . вариант 2 : он создается, у вас есть выбранный вами объект, вы можете вручную вызвать / вызвать функцию в установщике выбранного элемента