尝试使用视图模型中的命令通过数据绑定更新图像按钮中的图像源 - 不起作用

Trying to update an image source in an imagebutton with data binding using a command in the viewmodel - not working

请原谅新手问题,但我正在努力理解我哪里出错了...

我正在尝试通过绑定 xaml 中的图像源来更改图像按钮(在网格中):

    <ImageButton x:Name="playButton"
            Source="{Binding PlayImage}"
            Command="{Binding PlayCommand}"
            Grid.Row="1" 
            Grid.Column="0"
            BorderColor="#fafafa"
            BackgroundColor="#fafafa"
            />

ImageButton 最初加载正确的'play.png'。
命令 'PlayCommand' 正在处理绑定。这应该更改 PlayImage 的值以在用户单击图像按钮时显示 'pause.png' 图像。尽管 PlayImage 变量的值发生了变化,但图像不会更新。请有人能告诉我我错过了什么吗?这是我的视图模型:

    public class SermonDetailViewModel : BaseViewModel
{
    public Sermon Sermon { get; set; }
    public ICommand PlayCommand { private set; get; }

    private ImageSource _playImage;
    public ImageSource PlayImage
    {
        get { return _playImage; }
        set
        {
            _playImage = value;
            SetProperty(ref _playImage, value);
        }
    }


    public SermonDetailViewModel(Sermon sermon = null)
    {

        if (sermon != null)
        {
            Title = sermon.STitle;
            MP3Filepath = sermon.SLink;
            PlayCommand = new Command(async () => await StartPlayer());
            _playImage = "play.png";
        }
        Sermon = sermon;

    }

    async Task StartPlayer()
    { 

        await CrossMediaManager.Current.Play(MP3Filepath);

        _playImage = "pause.png";
        Console.WriteLine(_playImage);
        Console.WriteLine(PlayImage);

    }

这是我的 baseViewModel 代码,它使用 class INotifyPropertyChanged 并设置 setProperty 方法:

    public class BaseViewModel : INotifyPropertyChanged
{
    public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>();


    bool isBusy = false;
    public bool IsBusy
    {
        get { return isBusy; }
        set { SetProperty(ref isBusy, value); }
    }

    string title = string.Empty;
    public string Title
    {
        get { return title; }
        set { SetProperty(ref title, value); }
    }

    string mp3filepath = string.Empty;
    public string MP3Filepath
    {
        get { return mp3filepath; }
        set { SetProperty(ref mp3filepath, value); }
    }

    protected bool SetProperty<T>(ref T backingStore, T value,
        [CallerMemberName]string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

非常感谢您的帮助.....谢谢!

尝试

Source="{Binding PlayImage, Mode=TwoWay }"

这也可以帮助您进行绑定 https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/binding-mode

您正在设置私有支持字段,而不是 public 属性。这意味着 PropertyChanged 事件不会被引发

async Task StartPlayer()
    { 

        await CrossMediaManager.Current.Play(MP3Filepath);

        // should be PlayImage = "pause.png";
        _playImage = "pause.png";
        Console.WriteLine(_playImage);
        Console.WriteLine(PlayImage);
    }

我尝试了你的代码,做了一个样本来测试,我同意Jason的意见,请尝试设置PlayImage值,不要设置_playImage,我发现虽然PlayImage的值已经更新,但它是未绑定到 ImageButton。

请像下面的代码一样更改代码:

public SermonDetailViewModel(Sermon sermon = null)
{

    if (sermon != null)
    {
        Title = sermon.STitle;
        MP3Filepath = sermon.SLink;
        PlayCommand = new Command(async () => await StartPlayer());
        PlayImage= "play.png";
    }
    Sermon = sermon;

}

async Task StartPlayer()
{ 

    await CrossMediaManager.Current.Play(MP3Filepath);

    PlayImage= "pause.png";
    Console.WriteLine(_playImage);
    Console.WriteLine(PlayImage);

}

我也做了一个样例,你可以看看:

<ImageButton
            BackgroundColor="#fafafa"
            BorderColor="#fafafa"
            Command="{Binding PlayCommand}"
            HeightRequest="50"
            Source="{Binding PlayImage}"
            WidthRequest="50" />

 public partial class Page4 : ContentPage
{
    public Page4()
    {
        InitializeComponent();
        this.BindingContext = new SermonDetailViewModel();
    }
}

public class SermonDetailViewModel:ViewModelBase
{
    public ICommand PlayCommand { private set; get; }

    private ImageSource _playImage;
    public ImageSource PlayImage
    {
        get { return _playImage; }
        set
        {
            _playImage = value;
            RaisePropertyChanged("PlayImage");
        }
    }

    public SermonDetailViewModel()
    {
        PlayCommand = new Command(method1);
        _playImage = "check.png";
           
    }

    private void method1()
    {
       
        PlayImage = "plu3.png";

    }
}

它适用于代码:

    private ImageSource _playImage;
    public ImageSource PlayImage
    {
        get { return _playImage; }
        set
        {
            _playImage = value;
            Notify("PlayImage");
        }
    }

    protected void Notify(string propertyName)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    }