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="" FontFamily="../Ressources/fontawesome.ttf#FontAwesome"></Button>
<Button Grid.Column="4" Command="{Binding DeleteEintragCommand}" Text="" FontFamily="../Ressources/fontawesome.ttf#FontAwesome"></Button>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
В моем ViewModel есть все, что мне нужно, я проверил команды с помощью кнопки не в списке и отлично работает.
Если я навяжусь над привязкой, появится сообщение "Невозможно разрешить символ"..."
Ответы
Ответ 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="" 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="" 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 как частное свойство.