.NET MAUI中CollectionView内MediaElement的播放控制问题
解决方案
1. 给数据模型添加播放状态属性
在FactItem类中新增IsPlaying属性(需实现INotifyPropertyChanged接口,和现有属性保持一致):
private bool _isPlaying; public bool IsPlaying { get => _isPlaying; set { _isPlaying = value; OnPropertyChanged(); } }
2. 绑定MediaElement的播放状态
修改XAML中MediaElement的绑定逻辑,将播放状态与数据模型属性关联:
<MediaElement Source="{Binding MediaUrl}" IsPlaying="{Binding IsPlaying}" WidthRequest="300" HeightRequest="200" />
3. ViewModel中控制单一视频播放
在MainViewModel中维护当前播放项,确保同一时间只有一个视频播放:
private FactItem _currentPlayingItem; public FactItem CurrentPlayingItem { get => _currentPlayingItem; set { if (_currentPlayingItem != null) _currentPlayingItem.IsPlaying = false; _currentPlayingItem = value; if (_currentPlayingItem != null) _currentPlayingItem.IsPlaying = true; OnPropertyChanged(); } } // 绑定到列表项的点击事件,控制播放/切换 public ICommand PlayCommand => new Command<FactItem>(item => { CurrentPlayingItem = CurrentPlayingItem == item ? null : item; });
接着在XAML的ItemTemplate根布局中添加点击手势绑定:
<Grid.GestureRecognizers> <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type local:MainViewModel}}, Path=PlayCommand}" CommandParameter="{Binding .}" /> </Grid.GestureRecognizers>
4. 滚动出屏幕自动停止播放
在主页面代码后台(MainPage.xaml.cs)监听CollectionView的可见项变化事件,自动停止非可见项的播放:
private void CollectionView_VisibleItemsChanged(object sender, ItemsViewVisibleItemsChangedEventArgs e) { if (sender is CollectionView cv && cv.BindingContext is MainViewModel vm) { var visibleItems = cv.VisibleItems.Cast<FactItem>().ToList(); foreach (var item in vm.FactItems) { if (!visibleItems.Contains(item) && item.IsPlaying) { item.IsPlaying = false; } } } }
然后在XAML中给CollectionView绑定该事件:
<CollectionView ItemsSource="{Binding FactItems}" VisibleItemsChanged="CollectionView_VisibleItemsChanged">
关于获取单个MediaElement引用的说明
遵循MVVM原则,不建议在ViewModel中直接引用UI控件。如果确实需要在代码后台操作特定项的MediaElement,可通过Loaded事件建立控件与数据项的关联:
private Dictionary<FactItem, MediaElement> _mediaElementMap = new Dictionary<FactItem, MediaElement>(); private void MediaElement_Loaded(object sender, EventArgs e) { if (sender is MediaElement me && me.BindingContext is FactItem item) { if (!_mediaElementMap.ContainsKey(item)) _mediaElementMap.Add(item, me); } }
之后即可通过_mediaElementMap[item]获取对应项的MediaElement控件,执行播放/停止等操作。
内容的提问来源于stack exchange,提问作者Ed Mendez
相关产品推荐
相关产品推荐

