UWP: привязка событий ListView ItemTemplate MenuFlyOut к ViewModel - PullRequest
0 голосов
/ 29 августа 2018

У меня есть приложение UWP для управления паролями для веб-сайтов и учетных записей, но когда я написал его около 3 лет назад, я не очень хорошо знал MVVM, поэтому все обработчики событий находятся в коде View, и теперь я пытаюсь чтобы решить эту проблему и сделать ее более приверженной MVVM, переместив этот код в ViewModel.

Одна из имеющихся у меня функций - это всплывающее меню в каждом элементе ListView, поэтому пользователь может редактировать / удалять запись (и выполнять несколько других функций), но поскольку я определяю тип данных для шаблона данных ListView ItemTemplate, теперь не распознает привязку к обработчику событий Click в моей модели представления.

Как и следовало ожидать, моя ViewModel определена как в пространствах имен, так и в контексте данных страницы следующим образом:

    <Page ....
      xmlns:vm="using:PassPort.ViewModels"
      ...>

    <Page.DataContext>
        <vm:MainViewModel/>
    </Page.DataContext>

А вот мой ListView, и это ItemTemplate и DataTemplate. В каждом MenuFlyoutItem в FlyOut я пытаюсь сказать ему использовать обработчик в моей ViewModel, но он не может разрешить 'vm' - он показывает волнистую строку и говорит, что свойство 'vm' не найдено в типе 'Account' ' ,

    </ListView Name="lvwAccounts"  
               ItemsSource="{x:Bind vm.AccountsView}" 
               .....>
       <ListView.ItemTemplate>
        <DataTemplate x:DataType="model:Account">
            <Grid MinHeight="36" HorizontalAlignment="Left" RightTapped="AccountsList_RightTapped">

                <FlyoutBase.AttachedFlyout>
                    <MenuFlyout Placement="Bottom">
                        <MenuFlyoutItem x:Name="OpenWebsiteButton" Text="Open Website" Click="{x:Bind vm.FlyoutOpenWebsiteButton_Click}"/>
                        <MenuFlyoutItem x:Name="EditButton" Text="Edit Account" Click="{x:Bind vm.FlyoutEditButton_Click}"/>
                        <MenuFlyoutItem x:Name="AddButton" Text="Add Account" Click="{x:Bind vm. FlyoutAddButton_Click}"/>
                        <MenuFlyoutItem x:Name="DeleteButton" Text="Delete Account" Click="{x:Bind vm.FlyoutDeleteButton_Click}"/>
                    </MenuFlyout>
                </FlyoutBase.AttachedFlyout>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="150"/>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="150"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Row="0" Grid.Column="0" Text="{x:Bind AccountName}"  Foreground="{StaticResource Light}"
                           VerticalAlignment="Center" HorizontalAlignment="Stretch"/>

                <TextBlock Grid.Row="0" Grid.Column="1" Text="{x:Bind Category}"  Foreground="{StaticResource Light}"
                           VerticalAlignment="Center" HorizontalAlignment="Stretch" TextWrapping="Wrap" />

                <TextBlock Grid.Row="0" Grid.Column="2" Text="{x:Bind UserID}" Foreground="{StaticResource Light}"
                           VerticalAlignment="Center" HorizontalAlignment="Left"/>

                <TextBlock Grid.Row="0" Grid.Column="3" Text="{x:Bind Password}" Foreground="{StaticResource Light}"
                           VerticalAlignment="Center" HorizontalAlignment="Left" />

                <TextBlock Grid.Row="0" Grid.Column="4" Text="{x:Bind PasswordHint}" Foreground="{StaticResource Light}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Повсюду в коде 'vm' разрешается без проблем, поэтому кажется, что из-за DataType он не может / не сможет разрешить мою ссылку ViewModel.

Я также пытался использовать 'Click = "{Binding vm. [Обработчик событий]"}, но это не имеет значения - кто-нибудь знает, как я могу решить эту проблему?

1 Ответ

0 голосов
/ 29 августа 2018

В DataTemplate и x: Bind Microsoft говорит, что:

Внутри DataTemplate (используется ли он как шаблон элемента, шаблон содержимого или шаблон заголовка) значение Path интерпретируется не в контексте страницы, а в контексте объекта данных, который шаблонируется. Чтобы его привязки могли быть проверены (и эффективный код сгенерирован для них) во время компиляции, DataTemplate должен объявить тип своего объекта данных, используя x:DataType.

Чтобы связать ViewModel в DataTemplate, вам нужно использовать binding вместо x:bind, как этот код.

<ListView Name="lvwAccounts"  
          ItemsSource="{x:Bind vm.AccountsView}" >
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="model:Account">
                <FlyoutBase.AttachedFlyout>
                    <MenuFlyout Placement="Bottom">
                        <MenuFlyoutItem x:Name="OpenWebsiteButton" Text="Open Website" Command="{Binding ElementName=lvwAccounts,Path=DataContext.FlyoutOpenWebsite}"/>

                    </MenuFlyout>
                </FlyoutBase.AttachedFlyout>
        </DataTemplate>
    </ListView.ItemTemplate>      
</ListView>

Но binding в UWP не может связать метод, а binding может только связать Команду. Вы должны изменить свой метод на команду.

Я не могу найти свойство Command в MenuFlyoutItem, которое мы можем использовать для привязки события пользовательского интерфейса к команде во ViewModel, см. Связывание событий пользовательского интерфейса WPF с командами в ViewModel

См .: https://stackoverflow.com/a/40774956/6116637

Почему я не могу использовать {x: Bind {RelativeSource Self}} в шаблоне данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...