You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

我对只读Bindable Property的Getter实现是否正确?

你的Getter实现并不正确,这里是问题所在和修正方案

首先得明确:你自己在ViewModel里定义的VideoState属性,和Rox NuGet包中VideoView控件提供的只读VideoState属性是完全两个独立的东西。你的videoState字段从来没有被赋值过,所以它一直是VideoStateType枚举的默认值(大概率是Empty),这也是你控制台没看到有效输出的核心原因之一。

另外,你的Console.WriteLine写法也有问题:

Console.WriteLine("The VideoState is ", videoState);

这种写法不会把videoState的值插入到字符串里,你需要用占位符或者字符串插值:

// 占位符写法
Console.WriteLine("The VideoState is {0}", videoState);
// 字符串插值(C# 6+)
Console.WriteLine($"The VideoState is {videoState}");

正确的实现方式:监听VideoView的属性变化

要获取VideoView的真实VideoState,你需要监听控件本身的PropertyChanged事件,在事件触发时读取控件的VideoState属性,而不是自己定义一个同名属性。

步骤1:修正ViewModel的逻辑

把你自己定义的VideoState属性删掉,转而在属性变化方法里直接获取控件的VideoState值:

using System.ComponentModel;
using Xamarin.Forms;
using Rox;

namespace PreAppStructure
{
    public class RoxViewModel : INotifyPropertyChanged
    {
        private bool _isBusy;
        public bool IsBusy
        {
            get => _isBusy;
            set
            {
                _isBusy = value;
                OnPropertyChanged(nameof(IsBusy));
            }
        }

        // 用于接收VideoView的属性变化事件
        public void OnVideoViewPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(VideoView.VideoState))
            {
                if (sender is VideoView videoView)
                {
                    // 这里直接读取控件的VideoState属性
                    var currentState = videoView.VideoState;
                    Console.WriteLine($"The VideoState is {currentState}");
                    
                    // 根据状态设置IsBusy
                    IsBusy = currentState == VideoStateType.Buffering;
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

步骤2:在页面后台绑定事件

因为VideoView是XAML中的控件,你需要在页面的代码后台(Page3.xaml.cs)中把控件的PropertyChanged事件绑定到ViewModel的方法上:

using Xamarin.Forms;

namespace PreAppStructure
{
    public partial class Page3 : ContentPage
    {
        public Page3()
        {
            InitializeComponent();
            var viewModel = new RoxViewModel();
            BindingContext = viewModel;
            
            // 绑定VideoView的PropertyChanged事件到ViewModel的方法
            VideoView.PropertyChanged += viewModel.OnVideoViewPropertyChanged;
        }
    }
}

步骤3:调整XAML的命令绑定(可选)

如果你想用PropertyChangedCommand而不是直接绑定事件,需要确保ViewModel中有对应的ICommand属性,并传递控件实例:

// 在ViewModel中添加
public ICommand PropertyChangedCommand { get; }

// 在构造函数中初始化
public RoxViewModel()
{
    PropertyChangedCommand = new Command<object>((param) =>
    {
        if (param is PropertyChangedEventArgs args && args.PropertyName == nameof(VideoView.VideoState))
        {
            if (VideoView != null)
            {
                var currentState = VideoView.VideoState;
                IsBusy = currentState == VideoStateType.Buffering;
            }
        }
    });
}

对应的XAML调整:

<roxv:VideoView x:Name="VideoView" 
                AutoPlay="True" 
                LoopPlay="True" 
                ShowController="True" 
                Source="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4" 
                PropertyChangedCommand="{Binding PropertyChangedCommand}"
                PropertyChangedCommandParameter="{x:Reference VideoView}"/>

不过这种方式需要处理控件实例的传递,不如直接绑定事件直观。


为什么之前的控制台没有输出?

  1. 你的videoState字段从未被赋值,一直是枚举默认值,即使格式正确,输出的也是默认值。
  2. Console.WriteLine的格式错误,没有把变量插入到字符串中,所以只会输出固定文本,看不到变量值。

按照上面的修正方案,你应该能正确获取VideoView的状态,并且在Buffering时显示加载指示器了。

内容的提问来源于stack exchange,提问作者Tom F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:40:59