我正在使用 CollectionView,我需要导航到 SelectedChangedCommand 上的新页面。 但是绑定到 SelectedChangedCommand 的命令对于单个选择执行多次。 我有一个嵌套的 CollectionView。对于父 CollectionView SelectionChangedCommand,绑定命令执行两次,对于子 CollectionView SelectionChangedCommand,绑定命令执行多次。 请检查此图片以了解目标 UI
<CollectionView
x:Name="SpaceListCollectionView"
Grid.Row="1"
SelectionMode="Single"
SelectedItem="{Binding SelectedSpace}"
SelectionChangedCommand="{Binding OnSpaceClicked}"
ItemsSource="{Binding SpaceList}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="auto,auto">
<Grid
ColumnDefinitions="*,auto"
RowDefinitions="auto,auto"
Padding="26,10,22,0"
BackgroundColor="#f8f8f8"
Grid.Row="0">
<Label
Grid.Row="0"
Grid.Column="0"
Text="{Binding Space}"
VerticalOptions="Center"
FontAttributes="Bold"
Margin="0,0,0,10" />
<Image
Grid.Row="0"
Grid.Column="1"
Source="{Binding ArrowImage}"
WidthRequest="26"
VerticalOptions="Center"
Margin="0,0,0,7" />
<BoxView
Grid.Row="1"
Grid.ColumnSpan="2"
Color="#e7e7e7"
HeightRequest="1"
HorizontalOptions="FillAndExpand"
VerticalOptions="End" />
</Grid>
<CollectionView
Grid.Row="2"
Grid.ColumnSpan="2"
ItemsSource="{Binding Assets}"
SelectedItem="{Binding BindingContext.SelectedAsset, Source={x:Reference HomePage}}"
SelectionChangedCommand="{Binding BindingContext.OnAssetClicked, Source={x:Reference HomePage}}"
SelectionMode="Single"
IsVisible="{Binding IsExpanded}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid
ColumnDefinitions="auto,*,auto"
BackgroundColor="White"
ColumnSpacing="20"
Padding="10">
<Image
Grid.Column="0"
Source="asset_ready.png"
HeightRequest="45"/>
<Grid
Grid.Column="1"
RowDefinitions="auto,auto,auto"
VerticalOptions="Center">
<Label
Grid.Row="0"
Text="{Binding AssetType}"
FontSize="14"
FontAttributes="Bold"
IsVisible="{Binding BindingContext.IsGroupBySpace, Source={x:Reference HomePage}}" />
<Label
Grid.Row="0"
Text="{Binding Space}"
FontSize="14"
IsVisible="{Binding BindingContext.IsGroupByAssetType, Source={x:Reference HomePage}}"
FontAttributes="Bold" />
<Label
Grid.Row="1"
Text="{Binding AssetName}"
FontSize="12" />
<Label
Grid.Row="2"
Text="{Binding Barcode}"
FontSize="12" />
</Grid>
<Frame
Grid.Column="2"
VerticalOptions="Center"
HorizontalOptions="Center"
CornerRadius="50"
Padding="8,3"
BackgroundColor="#f0f0f0"
BorderColor="Transparent">
<Label
Text="{Binding TaskCount}"
BackgroundColor="#f0f0f0"
HorizontalTextAlignment="Center"/>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
我尝试设置
Command.CanExecute(false);
仍然执行命令。
我尝试了以下解决方案作为解决方法,但失败了。单击返回此页面将执行 OnAssetClicked 命令。
private bool _canExecute;
public ICommand OnAssetClicked => new Command(async () =>
{
if (_canExecute)
{
_canExecute = false;
await AssetClicked();
}
});
//Bound to Appearing EventToCommandBehavior
public ICommand OnAppearing => new Command(Initialize);
Private void Initialize()
{
_canExecute = true;
}
//will be called on parent collection view item selected.
private void Expand()
{
try
{
MainThread.BeginInvokeOnMainThread(() =>
{
var selectedSpace = SpaceList.FirstOrDefault(x => x.Space == SelectedSpace?.Space);
var index = SpaceList.IndexOf(selectedSpace ?? new AssetListModel());
if (selectedSpace != null)
{
selectedSpace.IsExpanded = !selectedSpace.IsExpanded;
if (selectedSpace.IsExpanded)
{
selectedSpace.ArrowImage = "key_up.png";
}
else
{
selectedSpace.ArrowImage = "key_down.png";
}
SpaceList[index] = selectedSpace;
}
});
}
catch (Exception ex) when (ex != null)
{
Debug.WriteLine(ex + " in HomePageViewModel ExpandArea");
}
finally
{
SelectedSpace = null;
}
}
//will be called on child collection view item selected
private async Task AssetClicked()
{
await NavigationService.Navigate(nameof(AssetDetailsPageView));
}
如何阻止
SelectionChangedCommand
多次执行。
在
Expand
方法中,您设置了 SpaceList[index] = selectedSpace;
,这会导致该方法执行两次。
如果您想更改
IsExpanded
属性并在运行时通知 UI,您可以为您的 Space 模型实现 INotifyPropertyChanged
接口,如下所示。
public class SpaceModel: INotifyPropertyChanged
{
public string Space { get; set; }
public ObservableCollection<Asset> Assets ...
public bool isExpanded;
public bool IsExpanded
{
get
{
return isExpanded;
}
set
{
isExpanded = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsExpanded)));
}
}
public event PropertyChangedEventHandler? PropertyChanged;
}
现在,当您更改 Space Item 的
IsExpand
属性时,它也会通知 UI 进行更改。然后您无需再次将值重置为 SpaceList
。只需删除,
SpaceList[index] = selectedSpace;
更多信息,您可以参考Viewmodels和属性更改通知,INotifyPropertyChanged接口。