C# 尝试使用viewmodel中的命令使用数据绑定更新imagebutton中的图像源-不起作用

C# 尝试使用viewmodel中的命令使用数据绑定更新imagebutton中的图像源-不起作用,c#,xamarin.forms,imagebutton,C#,Xamarin.forms,Imagebutton,请原谅新手的问题,但我正在努力理解我错在哪里 我试图通过在xaml中绑定图像源来更改imagebutton(在网格中): <ImageButton x:Name="playButton" Source="{Binding PlayImage}" Command="{Binding PlayCommand}" Grid.Row="1" Grid.Column="0"

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

我试图通过在xaml中绑定图像源来更改imagebutton(在网格中):

    <ImageButton x:Name="playButton"
            Source="{Binding PlayImage}"
            Command="{Binding PlayCommand}"
            Grid.Row="1" 
            Grid.Column="0"
            BorderColor="#fafafa"
            BackgroundColor="#fafafa"
            />
这是我的baseViewModel代码,它使用类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;
    }
公共类BaseViewModel:INotifyPropertyChanged
{
公共IDataStore数据存储=>DependencyService.Get();
bool isBusy=false;
公共图书馆很忙
{
获取{return isBusy;}
set{SetProperty(ref isBusy,value);}
}
string title=string.Empty;
公共字符串标题
{
获取{返回标题;}
集合{SetProperty(参考标题,值);}
}
string mp3filepath=string.Empty;
公共字符串MP3Filepath
{
获取{return mp3filepath;}
set{SetProperty(ref mp3filepath,value);}
}
受保护的布尔设置属性(参考T backingStore,T值,
[CallerMemberName]字符串propertyName=“”,
操作onChanged=null)
{
if(EqualityComparer.Default.Equals(backingStore,value))
返回false;
backingStore=价值;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
返回true;
}
我非常感谢您的帮助……谢谢!

试试看

Source="{Binding PlayImage, Mode=TwoWay }"
这也可以帮助您进行绑定 试试看

Source="{Binding PlayImage, Mode=TwoWay }"
这也可以帮助您进行绑定

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

async Task StartPlayer()
    { 

        await CrossMediaManager.Current.Play(MP3Filepath);

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

您正在设置私有支持字段,而不是公共属性。这意味着不会引发
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";

    }
}

公共部分类第4页:内容页
{
公共页4()
{
初始化组件();
this.BindingContext=新的SermonDetailViewModel();
}
}
公共类SermonDetailViewModel:ViewModelBase
{
公共ICommand播放命令{private set;get;}
私有ImageSource\u playImage;
公共图像源播放图像
{
获取{return\u playImage;}
设置
{
_playImage=值;
RaisePropertyChanged(“PlayImage”);
}
}
公共SermonDetailViewModel()
{
PlayCommand=新命令(方法1);
_playImage=“check.png”;
}
私有void方法1()
{
PlayImage=“plu3.png”;
}
}

我尝试了您的代码并做了一个示例测试,我同意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";

    }
}

公共部分类第4页:内容页
{
公共页4()
{
初始化组件();
this.BindingContext=新的SermonDetailViewModel();
}
}
公共类SermonDetailViewModel:ViewModelBase
{
公共ICommand播放命令{private set;get;}
私有ImageSource\u playImage;
公共图像源播放图像
{
获取{return\u playImage;}
设置
{
_playImage=值;
RaisePropertyChanged(“PlayImage”);
}
}
公共SermonDetailViewModel()
{
PlayCommand=新命令(方法1);
_playImage=“check.png”;
}
私有void方法1()
{
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));

    }

它与代码一起工作:

    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));

    }

谢谢,但此更改仍然没有更新图像。我是否缺少一个步骤或此更改是否有效?谢谢,但此更改仍然没有更新图像。我是否缺少一个步骤或此更改是否有效?谢谢您的建议,但图像仍然没有更新…谢谢您的建议,但图像仍然没有更新…谢谢您的帮助,我已经完成了en这一周都在挣扎!是SetProperty方法不起作用。我将其更改为使用RaisePropertyChanged方法,它起了作用。感谢您的帮助,我这一周都在挣扎!是SetProperty方法不起作用。我将其更改为使用RaisePropertyChanged方法,它起了作用。