【问题标题】:How to add to ObservableCollection with MVVM C#如何使用 MVVM C#​​ 添加到 ObservableCollection
【发布时间】:2020-09-16 23:53:32
【问题描述】:

我正在制作一个带有包含一些列表视图的选项卡式页面的 xamrin.forms 应用程序。所以我决定尝试 MVVM 方法,但我以前从未这样做过。我尝试从各种在线教程中学习,并且我了解了这个概念,但显然我缺少一些东西。

我希望用户能够通过单击按钮添加到列表中,但我只是不知道该怎么做。

模型包含一个名为 ConnectedProjectors 的类:

public class ConnectedProjectors
{
    public string ipaddress { get; set; }
    public string version { get; set; }
    public string swversion { get; set; }

    public Color activeStatus { get; set; }


    public override string ToString()
    {
        return ipaddress;
    }

}

在 ViewModel 中,我有 2 个类 ProjectorViewModel,它继承自 ViewModelBase:

 public class ProjectorViewModel : ViewModelBase
{
    private ProjectorServices service;


    public ProjectorViewModel()
    {
        service = new ProjectorServices();
        ProjectorList = new ObservableCollection<ConnectedProjectors>();
        ProjectorList = service.GetProjectors("test", "test", "test", Color.White); //Works as expected
    }

    public void AddProjector(string ip, string ver, string sw, Color color)
    {
        ProjectorList = service.GetProjectors(ip, ver, sw, color); //I expected this to add to the list
    }


    private ObservableCollection<ConnectedProjectors> connectedProjectors;
    public ObservableCollection<ConnectedProjectors> ProjectorList
    {
        get { return connectedProjectors; }
        set { SetProperty(ref connectedProjectors, value); } // Maybe the NotifyEvent doesn't work as expected?
    }

}

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value,
        [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

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

加上 ProjectorServices 类:

 class ProjectorServices
{
    public ProjectorServices()
    {

    }

    public ObservableCollection<ConnectedProjectors> GetProjectors(string ipad, string ver, string sw, Color color)
    {
        var list = new ObservableCollection<ConnectedProjectors>
        {
            new ConnectedProjectors
            {
                ipaddress = ipad,
                version = ver,
                swversion = sw,
                activeStatus = color                   
            }
        };

        return list;
    }
}

最后是 MainPage 类:

   public partial class MainPage : ContentPage
{
    public ConnectedProjectors projectors;
    private ProjectorViewModel projvm = new ProjectorViewModel();
    public MainPage()
    {
        InitializeComponent();

        this.BindingContext = new ProjectorViewModel();
    }
     public void AddProj(object sender,EventArgs e)
    {
        string ip = txt.Text;  // text input in editor in MainView view.
        string pn = "Not Found";
        string sw = "Not Found";
        Color col = Color.Chocolate;

        try
        {
            pn = GetPartNr(ip); // Sends an ascii command to see if the ipaddress returns an expected result
            sw = GetSWVersion(ip);
            col = GetActiveStatus(ip);
        }

        finally
        {
            projvm.AddProjector(ip, pn, sw, col);
        }
    }
}

现在的代码结果是,在应用程序按预期初始化时,ProjectorViewModel() 方法中的命令添加到 Observable 集合中。但是在我刚刚在下面编写的方法 AddProjector() 中,相同的命令不会向集合中添加新项目(至少在列表视图中不可见)。

在 XAML 中,我将 listview ItemSource 绑定到 ProjectorList,并且 listview 显示测试项目,但是当我单击触发 AddProj()Method 的按钮时,没有任何反应。

我认为问题是以下两种情况之一:

  1. 我尝试添加到收藏的方式不正确

  2. PropertyChanged 没有按预期工作

我希望有人可以帮助我解决这个问题。任何帮助将不胜感激。

【问题讨论】:

    标签: c# xamarin mvvm xamarin.forms


    【解决方案1】:

    你的问题是正确的。您的MainPage 将其BindingContext 设置为ProjectorViewModel 的新实例。

    this.BindingContext = new ProjectorViewModel();
    

    但是,AddProj 方法将新的 ViewModel 添加到 projvm,这只是一个私有字段,坐在那里。它与页面及其绑定没有任何关系。更好的方法是在属性中公开 BindingContext 的 ViewModel 并使用它。

    public ProjectorViewModel ViewModel
    {
        get => this.BindingContext as ProjectorViewModel;
        set => this.BindingContext = value;
    }
    

    然后你可以像这样设置你的 BindingContext:

    public HomePage()
    {
        InitializeComponent();
    
        this.ViewModel = new ProjectorViewModel();
    }
    

    通过这种方式,我们再次设置了上下文,但这次我们可以访问它。现在,您可以像这样添加新的 ViewModel:

    this.ViewModel.AddProjector(ip, pn, sw, col);
    

    现在您将使用与您的页面绑定的同一个实例。

    【讨论】:

    • 非常感谢您的回复 Mihail。我会尝试这样做。
    猜你喜欢
    • 1970-01-01
    • 2018-12-23
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多