假设我有一个具有多个属性(如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,正在实现所需的接口。
感谢您的帮助!
答案 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数据。
希望这有帮助。