Xamarin Forms - SelectionChangedCommand 没有为 CollectionView 触发
Xamarin Forms - SelectionChangedCommand not firing for CollectionView
下面的代码显示了 CollectionView 的一个简单示例。我没有收到 SelectionChangedCommand 的事件。有人能看出我做错了什么吗?
顺便说一句,可以在 GitHub here.
上找到完整的源代码
MainPage.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"
xmlns:local="clr-namespace:ControlDemo"
x:Class="ControlDemo.MainPage">
<StackLayout>
<CollectionView SelectionMode ="Single"
ItemsSource="{Binding Tags}"
SelectionChangedCommand="{Binding SelectedTagChanged}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
MainPageModel.cs
public class MainPageModel : FreshBasePageModel
{
public override void Init(object initData)
{
Tags = new List<string>() { "A", "B", "C" };
base.Init(initData);
}
public List<string> Tags { get; set; }
public Command SelectedTagChanged
{
get
{
return new Command(() =>
{
});
}
}
}
您似乎没有设置 SelectionMode 属性。根据 docs:
By default, CollectionView selection is disabled. However, this behavior can be changed by setting the SelectionMode property value to one of the SelectionMode enumeration members:
- None – indicates that items cannot be selected. This is the default value.
- Single – indicates that a single item can be selected, with the selected item being highlighted.
- Multiple – indicates that multiple items can be selected, with the selected items being highlighted.
将 SelectionMode = Single
添加到 CollectionView 将解决您的问题。
如果你想使用你的 ViewModel,那么你应该使用 SelectedItem 的绑定:
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectedItem="{Binding SelectedMonkey, Mode=TwoWay}">
...
</CollectionView>
并且,在您的 ViewModel 中:
Monkey selectedMonkey;
public Monkey SelectedMonkey
{
get
{
return selectedMonkey;
}
set
{
if (selectedMonkey != value)
{
selectedMonkey = value;
}
}
}
所以每次 select 一个新对象时,SelectedMonkey 都会更新。
如果你想跟踪 SelectionChanged,那么,它应该在 code-behind 中(不确定如何在视图模型中实现,文档中没有相关内容)
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectionChanged="OnCollectionViewSelectionChanged">
...
</CollectionView>
并且,在您的 Page.xaml.cs 中:
void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var previous = e.PreviousSelection;
var current = e.CurrentSelection;
...
}
我使用你的代码并在我这边创建了一个演示,我添加了 widthRequest
和 HeightRequest
以使 collectionView 工作:
<CollectionView
HeightRequest="170"
WidthRequest="200"
SelectionMode="Single"
SelectionChangedCommand="{Binding SelectedTagChangedCommand}"
ItemsSource="{Binding Tags}"
>
在我单击 CollectionView 中的不同项目后确实触发了 SelectionChangedCommand
。
我在这里上传了一个样本,你可以查看:collectionView-selectItemChanged-xamarin.forms
我身边的一些事情(除了 SelectionMode = Single
):
确保您的命令签名在您的 PageModel 中是 <object>
并根据您的需要进行任何转换(特别是如果您的集合变得更复杂)。
另外,在您的 XAML 中,您想为 CollectionView 命名并使用 SelectedItem 属性。
SelectionChangedCommandParameter="{Binding SelectedItem, Source={x:Reference cvTagsCollectionView}}"
如果你正在使用它的模型,你可以使用下面的方法
我的 C# 模型视图 Class
public class MainView : INotifyPropertyChanged
{
public ICommand SelectionChangedCommands => new Command<GroupableItemsView>((GroupableItemsView query) =>
{
GO_Account test = query.SelectedItem as GO_Account;
});
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
这是我的 XAML
<CollectionView x:Name="myAccounts"
SelectionMode="Single"
ItemsSource="{Binding Products}"
SelectionChangedCommand="{Binding SelectionChangedCommands}"
SelectionChangedCommandParameter="{Binding Source={x:Reference myAccountsModel}}">
</CollectionView>
我改进了 Fabricio P. 的回答:
- 将 {RelativeSource Self} 用于 SelectionChangedCommandParameter。它有助于省略命名集合视图。
所以你的 xaml 部分将是这样的:
<CollectionView
ItemsSource="{Binding Objects}"
SelectionMode="Single"
SelectionChangedCommand="{Binding SelectObjectCommand}"
SelectionChangedCommandParameter="{Binding SelectedItem, Source={RelativeSource Self}}">
并且在您的视图模型中:
public ICommand SelectObjectCommand => new Command<string>(i => { Debug.WriteLine("Selected: " + i); });
public IEnumerable<string> Objects { get; set; }
下面的代码显示了 CollectionView 的一个简单示例。我没有收到 SelectionChangedCommand 的事件。有人能看出我做错了什么吗?
顺便说一句,可以在 GitHub here.
上找到完整的源代码MainPage.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"
xmlns:local="clr-namespace:ControlDemo"
x:Class="ControlDemo.MainPage">
<StackLayout>
<CollectionView SelectionMode ="Single"
ItemsSource="{Binding Tags}"
SelectionChangedCommand="{Binding SelectedTagChanged}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
MainPageModel.cs
public class MainPageModel : FreshBasePageModel
{
public override void Init(object initData)
{
Tags = new List<string>() { "A", "B", "C" };
base.Init(initData);
}
public List<string> Tags { get; set; }
public Command SelectedTagChanged
{
get
{
return new Command(() =>
{
});
}
}
}
您似乎没有设置 SelectionMode 属性。根据 docs:
By default, CollectionView selection is disabled. However, this behavior can be changed by setting the SelectionMode property value to one of the SelectionMode enumeration members:
- None – indicates that items cannot be selected. This is the default value.
- Single – indicates that a single item can be selected, with the selected item being highlighted.
- Multiple – indicates that multiple items can be selected, with the selected items being highlighted.
将 SelectionMode = Single
添加到 CollectionView 将解决您的问题。
如果你想使用你的 ViewModel,那么你应该使用 SelectedItem 的绑定:
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectedItem="{Binding SelectedMonkey, Mode=TwoWay}">
...
</CollectionView>
并且,在您的 ViewModel 中:
Monkey selectedMonkey;
public Monkey SelectedMonkey
{
get
{
return selectedMonkey;
}
set
{
if (selectedMonkey != value)
{
selectedMonkey = value;
}
}
}
所以每次 select 一个新对象时,SelectedMonkey 都会更新。
如果你想跟踪 SelectionChanged,那么,它应该在 code-behind 中(不确定如何在视图模型中实现,文档中没有相关内容)
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectionChanged="OnCollectionViewSelectionChanged">
...
</CollectionView>
并且,在您的 Page.xaml.cs 中:
void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var previous = e.PreviousSelection;
var current = e.CurrentSelection;
...
}
我使用你的代码并在我这边创建了一个演示,我添加了 widthRequest
和 HeightRequest
以使 collectionView 工作:
<CollectionView
HeightRequest="170"
WidthRequest="200"
SelectionMode="Single"
SelectionChangedCommand="{Binding SelectedTagChangedCommand}"
ItemsSource="{Binding Tags}"
>
在我单击 CollectionView 中的不同项目后确实触发了 SelectionChangedCommand
。
我在这里上传了一个样本,你可以查看:collectionView-selectItemChanged-xamarin.forms
我身边的一些事情(除了 SelectionMode = Single
):
确保您的命令签名在您的 PageModel 中是
<object>
并根据您的需要进行任何转换(特别是如果您的集合变得更复杂)。另外,在您的 XAML 中,您想为 CollectionView 命名并使用 SelectedItem 属性。
SelectionChangedCommandParameter="{Binding SelectedItem, Source={x:Reference cvTagsCollectionView}}"
如果你正在使用它的模型,你可以使用下面的方法
我的 C# 模型视图 Class
public class MainView : INotifyPropertyChanged
{
public ICommand SelectionChangedCommands => new Command<GroupableItemsView>((GroupableItemsView query) =>
{
GO_Account test = query.SelectedItem as GO_Account;
});
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
这是我的 XAML
<CollectionView x:Name="myAccounts"
SelectionMode="Single"
ItemsSource="{Binding Products}"
SelectionChangedCommand="{Binding SelectionChangedCommands}"
SelectionChangedCommandParameter="{Binding Source={x:Reference myAccountsModel}}">
</CollectionView>
我改进了 Fabricio P. 的回答:
- 将 {RelativeSource Self} 用于 SelectionChangedCommandParameter。它有助于省略命名集合视图。
所以你的 xaml 部分将是这样的:
<CollectionView
ItemsSource="{Binding Objects}"
SelectionMode="Single"
SelectionChangedCommand="{Binding SelectObjectCommand}"
SelectionChangedCommandParameter="{Binding SelectedItem, Source={RelativeSource Self}}">
并且在您的视图模型中:
public ICommand SelectObjectCommand => new Command<string>(i => { Debug.WriteLine("Selected: " + i); });
public IEnumerable<string> Objects { get; set; }