ViewModel或Model中的MVVM RaisePropertyChanged?

时间:2016-04-07 14:11:10

标签: c# mvvm mvvm-light

假设我有一个具有多个属性(如Ping)的Server类,它们在后台更新。 我有一个ServerViewModel,它持有Server实例和ServersViewModel,它在ObservableCollection中保存ServerViewModel的不同实例,以在View中的List中显示服务器。

(缩短的)服务器类:

public class Server: ObservableObject, IServer 
{

    /// <summary>
    /// Gets the IP adress of the server
    /// </summary>
    [JsonIgnore]
    public IPAddress IPAdress { get; private set; }

    /// <summary>
    /// Gets the name of the server
    /// </summary>
    public string Name
    {
        get
        {
            return name;
        }

        private set
        {
            if(name != value)
            {
                name = value;
                RaisePropertyChanged("Name");
            }

        }
    }

    /// <summary>
    /// Gives the string of the ip
    /// </summary>
    public string IP
    {
        get
        {
            return ip;
        }

        private set
        {
            if(ip != value)
            {
                ip = value;
                RaisePropertyChanged("IP");
            }                
        }
    }


    /// <summary>
    /// Gets the ping of the server
    /// </summary>
    [JsonIgnore]
    public int Ping
    {
        get
        {
            return ping;
        }

        private set
        {
            if(ping != value)
            {
                ping = value;
                RaisePropertyChanged("Ping");
            }
        }
    }

    private Thread queryThread;

    private string name, ip;

    /// <summary>
    /// Initializes the server instance
    /// </summary>
    /// <param name="ip">The ip adress or dns of the server</param>
    /// <param name="port">The common port to connect to</param>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Server(string ip, int port)
    {
        IP = ip;

        IPAddress tmpIP;

        // Check if the given IP matches a DNS
        if (!IPAddress.TryParse(ip, out tmpIP))
        {
            try
            {
                this.IPAdress = Dns.GetHostEntry(ip).AddressList[0];
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
                return;
            }
        }
        else
        {
            this.IPAdress = IPAddress.Parse(ip);
        }

        Port = port;

        queryThread = new Thread(QueryServer);
        queryThread.Start();
    }

    /// <summary>
    /// Destructor for Server class. Stops the server thread running in background and cleans up.
    /// </summary>
    ~Server()
    {
        try
       {
            queryThread.Abort();
            queryThread = null;
        }
        catch
        {
            // Ignored
        }
    }

    /// <summary>
    /// Starts the loop that is querying the server
    /// </summary>
    private void QueryServer()
    {
    }
}

当我在后台更新数据时,我在需要它的Proerties中添加了RaisePropertyChanged。

ServerViewModel:

public class ServerViewModel: ViewModelBase
{
    private Server server;

    public Server Server
    {
        get
        {
            return server;
        }
    }

    public ServerViewModel(Server server)
    {
        this.server = server;
    }
}

ServersViewModel:

public class ServersViewModel: ObservableObject
{
    #region Members

    ObservableCollection<ServerViewModel> servers = new ObservableCollection<ServerViewModel>();

    #endregion

    #region Properties
    public ObservableCollection<ServerViewModel> Servers
    {
        get
        {
            return servers;
        }

        set
        {
            servers = value;
        }
    }
    #endregion

    #region Construction
    public ServersViewModel()
    {
        // Add servers to the collection
    }
    #endregion
}

我将ServersViewModel绑定到视图中的列表。我对列表中每个项目的DataBinding如下所示:

<Label  Name="lblServerPing" Content="{Binding Server.Ping}" />

对我来说这看起来不错。特别是因为我正在访问视图的Server实例而不是视图的属性。我仍然不知道在哪里放RaisePropertyChanged以及如何解决这个问题。我必须承认它正在以这种方式工作,但我认为它不是它在MVVM中的样子。

ObservableObject和ViewModelBase来自MVVM,正在实现所需的接口。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

通常,应在ViewModel中引发PropertyChanged事件,模型应该只是属性/对象的集合。然后,ViewModel将公开这些属性,并在它们通过PropertyChanged事件进行更改时通知视图。

这是你正在做的事情的简化版本,如果你想严格遵守MVVM,那么它应该会描绘出去往何处的图片......

public class ServerModel
{
    public string Name { get; set; }
    public string IP { get; set; }
}

public class ServerViewModel : ViewModelBase
{
    private ServerModel model;

    public ServerViewModel(ServerModel model)
    {
        this.model = model;
    }

    public string Name
    {
         get { return model.Name; }
         private set
         {
              model.Name = value;
              OnPropertyChanged("Name");
         }
    }

    public string IP
    {
         get { return model.IP; }
         private set
         {
              model.IP= value;
              OnPropertyChanged("IP");
         }
    }
}

setter中的验证逻辑将放在ViewModel中。如果ViewModel中的逻辑变得复杂,理想情况下应将其外包给服务类 - ViewModels不应包含许多复杂的逻辑,它们只是告诉Views如何显示Model数据。

希望这有帮助。