предположим, что у меня есть класс Server с несколькими свойствами (такими как Ping), которые обновляются в фоновом режиме. У меня есть ServerViewModel, который хранит экземпляр сервера и ServersViewModel, который держит разные экземпляры ServerViewModel в ObservableCollection, чтобы отображать серверы в списке в представлении.MVVM RaisePropertyChanged в ViewModel или Model?
The (укороченный) Class Server:
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()
{
}
}
Как я обновляю данные в фоновом режиме, я добавил RaisePropertyChanged в Proerties, где это необходимо.
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 и реализуют необходимые интерфейсы.
Благодарим за помощь!
Спасибо. Именно в этом я неправильно понял эту концепцию. Таким образом, я мог бы перемещать поток рабочего потока в модель представления и позволить этому потоку обновлять сервер? Вот как я буду в этом случае. – chris579