Xamarin Forms Button Командная строка внутри ListView

У меня есть следующая проблема, на мой взгляд, у меня есть Listview. В этом списке я хотел бы иметь две кнопки. Один для редактирования элемента, один для его удаления.

Вот мой список в XAML

<ListView Grid.Row="1" x:Name="ArbeitsEinträgeList" ItemsSource="{Binding EintragList}" SelectedItem="{Binding SelectedItem}">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition/>
                  <ColumnDefinition/>
                  <ColumnDefinition/>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Label Text="{Binding Titel}" TextColor="{Binding Fehlerhaft, Converter={StaticResource EintragartConverter}}"></Label>
                <Label Grid.Column="1" Text="{Binding Beginn}" TextColor="{Binding BeginnManuell, Converter={StaticResource EintragartConverter}}"></Label>
                <Label Grid.Column="2" Text="{Binding Ende}" TextColor="{Binding EndeManuell, Converter={StaticResource EintragartConverter}}"></Label>
                <Button Grid.Column="3" Command="{Binding EditEintragCommand}" Text="&#xf040;" FontFamily="../Ressources/fontawesome.ttf#FontAwesome"></Button>
                <Button Grid.Column="4" Command="{Binding DeleteEintragCommand}" Text="&#xF00D;" FontFamily="../Ressources/fontawesome.ttf#FontAwesome"></Button>
              </Grid>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

В моем ViewModel есть все, что мне нужно, я проверил команды с помощью кнопки не в списке и отлично работает.

Если я навяжусь над привязкой, появится сообщение "Невозможно разрешить символ"..."

Cannot resolve symbol

Ответ 1

Ян,

Поскольку вы использовали представление списка, а ваши команды находятся внутри DataTemplate, привязка привязывается к контексту привязки каждой отдельной модели в ItemSource.

Способ вокруг этого заключается в следующем:

<ListView Grid.Row="1" x:Name="ArbeitsEinträgeList" ItemsSource="{Binding EintragList}" SelectedItem="{Binding SelectedItem}">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <Grid x:Name="Item">
                <Grid.ColumnDefinitions>
                  <ColumnDefinition/>
                  <ColumnDefinition/>
                  <ColumnDefinition/>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Label Text="{Binding Titel}" TextColor="{Binding Fehlerhaft, Converter={StaticResource EintragartConverter}}"></Label>
                <Label Grid.Column="1" Text="{Binding Beginn}" TextColor="{Binding BeginnManuell, Converter={StaticResource EintragartConverter}}"></Label>
                <Label Grid.Column="2" Text="{Binding Ende}" TextColor="{Binding EndeManuell, Converter={StaticResource EintragartConverter}}"></Label>
                <Button Grid.Column="3" BindingContext="{Binding Source={x:Reference ArbeitsEinträgeList}, Path=BindingContext}"   Command="{Binding EditEintragCommand}"   CommandParameter="{Binding Source={x:Reference Item}, Path=BindingContext}" Text="&#xf040;" FontFamily="../Ressources/fontawesome.ttf#FontAwesome"></Button>
                <Button Grid.Column="4" BindingContext="{Binding Source={x:Reference ArbeitsEinträgeList}, Path=BindingContext}" Command="{Binding DeleteEintragCommand}"  CommandParameter="{Binding Source={x:Reference Item}, Path=BindingContext}" Text="&#xF00D;" FontFamily="../Ressources/fontawesome.ttf#FontAwesome"></Button>
              </Grid>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

Поэтому вы устанавливаете источник привязки для ссылки на контекст привязки вида списка (т.е. Вашу модель представления или "ArbeitsEinträgeList"). Вы также можете установить параметр команды в контексте привязки каждого отдельного элемента. Как видите, у меня есть x: Name = "Item" в сетке и CommandParameter = "{Binding Source = {x: Reference Item}, Path = BindingContext}".

Просто объявление таких команд позволяет вам определить общую команду в вашей модели представления и когда команда выполняется с параметром команды, являющимся контекстом привязки отдельного элемента.

 public ICommand DeleteEintragCommand
        {
            get
            {
                return new Command((e) =>
                    {
                        var item = (e as MyModelObject);
                        // delete logic on item
                    });
            }
        }

Ответ 2

Это связано с тем, что вы привязываетесь к элементу в EintragList - (почему ваша привязка к текстовым свойствам, например Beginn и Ende). И командная привязка пытается получить команду в одном элементе из вашего списка, а не из вашей модели viewmodel.

Вариант 1: вы устанавливаете команду в своем классе предметов и обрабатываете ее.

Вариант 2. Расскажите о своей привязке, что источником должна быть ваша страница (а не отдельный элемент):

Command="{Binding BindingContext.EditEintragCommand, Source={x:Reference Name=MyPageName}}"

Просто убедитесь, что имя корневого элемента ваших страниц задано x:Name="MyPageName"

Чтобы узнать, какой элемент запускает команду, вы можете установить свойство CommandParameter, которое затем также отправляется команде в качестве объекта:

CommandParameter="{Binding .}"

Дополнительно: когда вы используете внешние шаблоны для отображения элементов в своем списке, вы можете попробовать что-то, что я описал в другом ответе (тот же принцип).

Ответ 3

Если вы хотите связать нажатие кнопки, вы также можете попробовать использовать событие Clicked в атрибуте Button. Вот мой код и его работа для меня

  <ListView x:Name="lst1" RowHeight="80">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Vertical" Padding="8,0,8,0">
                        <Label Text="{Binding Fname}" TextColor="#000" FontSize="14" LineBreakMode="TailTruncation" />
                        <Label Text="{Binding Mobile}" TextColor="#000" LineBreakMode="TailTruncation" />
                        <Button Text="Remove" Clicked="Delete" CommandParameter="{Binding ID}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

и на стороне кода вы можете просто реализовать метод удаления с аргументом типа

   public void Delete(Object Sender, EventArgs args)
    {
        Button button = (Button)Sender;
        string ID = button.CommandParameter.ToString();
        // Do your Stuff.....
    }

Ответ 4

Вот еще одна вещь, которая может застать вас врасплох. Привязка к команде никогда не произойдет, если вы случайно определите свою ICommand в ViewModel как частное свойство.