SingleMessage.xaml将viewmodel作为SingleMessageViewModel.cs,此viewmodel使用LogAcitvity类作为属性,并且viewmodel中定义的属性绑定到SingleMessage.xaml。 现在我想在SocketClient.cs(Model)中使用this(viewmodel)属性,并希望在viewmodel中通知属性更改以更新视图。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
LogActivity类,其属性在viewmodel中使用
public class LogActivity : ViewModelBase
{
private string messageLog;
public string MessageLog
{
get { return messageLog; }
set
{
if (value != messageLog)
{
messageLog = value;
NotifyPropertyChanged("MessageLog");
}
}
}
}
这是我的viewmodel类
public class SingleMessageViewModel : ViewModelBase
{
private LogActivity messagelog;
public SingleMessageViewModel()
{
messagelog = new LogActivity();
}
public LogActivity MessageLog
{
get { return messagelog; }
set
{
if (value != messagelog)
{
messagelog = value;
NotifyPropertyChanged("MessageLog");
}
}
}
}
这是我的观点
<TextBox x:Name="TxtLog" Text="{Binding MessageLog.MessageLog, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" />
现在我想在我的SocketClient.cs模型类的viewmodel中使用此MessageLog属性,并希望将其更改通知viewmodel。 这样更新就会发生。而且这个问题在异步方法调用中也有所改变,所以我想使用这个语法来更新viewmodel属性:
public class SocketClient : INotifyPropertyChanged
{
App.Current.Dispatcher.BeginInvoke((Action)delegate
{
MessageLog.MessageLog += messageTimeStamp + " : <- " + szData.Replace("\n\0", "") + "\n";
});
}
那么,如何在模型中使用viewmodel propety并将其通知给viewmodel
public LogActivity MessageLog
{
get { return messagelog; }
set
{
if (value != messagelog)
{
messagelog = value;
NotifyPropertyChanged("MessageLog");
}
}
}
我的模特看起来像这样..
namespace PCSTESTGUI.Models
{
public class SocketClient : INotifyPropertyChanged
{
// Receive buffer.
byte[] dataBuffer = new byte[256];
IAsyncResult result;
public AsyncCallback pfnCallBack;
public Socket clientSocket;
private LogActivity messagelog;
//private SingleMessageViewModel SingleMVM;
int portNo;
string ipAddress;
string filePathName;
string receivedResponse;
string message = string.Empty;
string connstring = ConfigurationManager.AppSettings["XmlConfigurationSetting"].ToString();
string fileName = ConfigurationManager.AppSettings["XmlConfiguratonSettingFileName"].ToString();
string messageTimeStamp = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString();
public SocketClient()
{
messagelog = new LogActivity();
SingleMessageViewModel SingleMVM = new SingleMessageViewModel(this);
//get the IPAddress and PortNo from save configuration setting
filePathName = connstring + "\\" + fileName;
try
{
if (File.Exists(filePathName))
{
XDocument xdoc = XDocument.Load(filePathName);
var configsetting = from cs in xdoc.Descendants("ConfigurationSetting")
select cs;
foreach (var config in configsetting)
{
ipAddress = config.Element("IPAddress").Value;
portNo = Convert.ToInt16(config.Element("PortNo").Value);
}
// check ipaddress and port no exists
if (ipAddress == "" || portNo == 0)
{
MessageBox.Show("IP Address and Port Number are required to connect to the Server\n", "Socket Connection : Missing", MessageBoxButton.OK, MessageBoxImage.Error);
FileLogger.Handle("Missing IP Address / Port Number in the configuration settings file");
MessageLog.MessageLog += messageTimeStamp + " : Missing IP Address / Port Number in the configuration settings file\n";
return;
}
//connect to the server
ConnectServer();
}
}
catch (Exception ex)
{
FileLogger.Handle(ex.Message);
MessageLog.MessageLog += messageTimeStamp + " : " + ex.Message + "\n";
}
}
public SingleMessageViewModel SingleMVM
{
get;
set;
}
public LogActivity MessageLog
{
get
{
return messagelog;
}
set
{
messagelog = value;
this.SingleMVM.MessageLog = value;
NotifyPropertyChanged("MessageLog");
}
}
public void ConnectServer()
{
try
{
// Get the remote IP address
IPAddress ip = IPAddress.Parse(ipAddress);
int iPortNo = portNo;
// Create the socket instance
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
FileLogger.Handle("StartConnect - Trying socket connection to PCS server '" + ip.ToString() + "' on Port " + iPortNo.ToString());
MessageLog.MessageLog += messageTimeStamp + " : StartConnect - Trying socket connection to PCS server '" + ip.ToString() + "' on Port " + iPortNo.ToString() + "\n";
// Create the end point
IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);
// Connect to the remote host
clientSocket.Connect(ipEnd);
if (clientSocket.Connected)
{
FileLogger.Handle("ProcessConnect - Client socket connected to PCS server '" + ip.ToString() + "' on Port " + iPortNo.ToString());
MessageLog.MessageLog += messageTimeStamp + " : ProcessConnect - Client socket connected to PCS server '" + ip.ToString() + "' on Port " + iPortNo.ToString() + "\n";
//Wait for data asynchronously
WaitForData();
}
else
{
ConnectServer();
}
}
catch (SocketException ex)
{
FileLogger.Handle(ex.Message);
MessageLog.MessageLog += messageTimeStamp + " : " + ex.Message + "\n";
}
}
public void SendMessage(string message)
{
try
{
if (!clientSocket.Connected)
ConnectServer();
if (message != "")
{
this.message = message + "\r\n";
byte[] byteMessage = Encoding.ASCII.GetBytes(this.message);
//NetworkStream networkStream = new NetworkStream(clientSocket);
//StreamWriter streamWriter = new StreamWriter(networkStream);
//streamWriter.WriteLine(byteMessage);
//streamWriter.Flush();
if (clientSocket != null && clientSocket.Connected)
{
FileLogger.Handle("Pseudo Command message processing tasks started");
FileLogger.Handle(" -> " + message.ToUpper());
MessageLog.MessageLog += messageTimeStamp + " : Pseudo Command message processing tasks started\n";
MessageLog.MessageLog += messageTimeStamp + " : -> " + message.ToUpper() + "\n";
clientSocket.Send(byteMessage);
}
else
{
ConnectServer();
if (clientSocket.Connected)
{
FileLogger.Handle("Pseudo Command message processing tasks started");
FileLogger.Handle(" -> " + message.ToUpper());
MessageLog.MessageLog += messageTimeStamp + " : Pseudo Command message processing tasks started\n";
MessageLog.MessageLog += messageTimeStamp + " : -> " + message.ToUpper() + "\n";
clientSocket.Send(byteMessage);
}
}
}
}
catch (Exception ex)
{
FileLogger.Handle(ex.Message);
MessageLog.MessageLog += messageTimeStamp + " : " + ex.Message + "\n";
}
}
public void DissconnectServer()
{
clientSocket.Close();
clientSocket = null;
FileLogger.Handle("CloseConnection - Closed socket connection to PCS server '" + ipAddress + "' on Port " + portNo.ToString());
MessageLog.MessageLog += messageTimeStamp + " : ProcessConnect - Client socket connected to PCS server '" + ipAddress + "' on Port " + portNo.ToString() + "\n";
}
public class SocketPacket
{
public System.Net.Sockets.Socket thisSocket;
public byte[] dataBuffer = new byte[1024];
}
public void WaitForData()
{
try
{
if (pfnCallBack == null)
{
pfnCallBack = new AsyncCallback(OnDataReceived);
}
SocketPacket theSocPkt = new SocketPacket();
theSocPkt.thisSocket = clientSocket;
// Start listening to the data asynchronously
result = clientSocket.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length,
SocketFlags.None, pfnCallBack, theSocPkt);
if (result.IsCompleted == false)
{
Console.Write(".");
}
}
catch (SocketException se)
{
FileLogger.Handle(se.Message);
MessageLog.MessageLog += messageTimeStamp + " : " + se.Message + "\n";
}
}
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
System.String szData = new System.String(chars);
receivedResponse = receivedResponse + szData + "\n";
if (szData.ToString() != "\0" || szData.ToString() != "")
{
FileLogger.Handle(" <- " + szData.Replace("\n\0", ""));
App.Current.Dispatcher.BeginInvoke((Action)delegate
{
MessageLog.MessageLog += messageTimeStamp + " : <- " + szData.Replace("\n\0", "") + "\n";
if (SingleMVM == null)
SingleMVM = new SingleMessageViewModel(this);
//this.SingleMVM.MessageLog.MessageLog += this.MessageLog.MessageLog;
this.SingleMVM.updateMesssage(szData.Replace("\n\0", ""));
});
}
WaitForData();
}
catch (ObjectDisposedException ex)
{
FileLogger.Handle(ex.Message);
MessageLog.MessageLog += messageTimeStamp + " : " + ex.Message + "\n";
}
catch (SocketException se)
{
FileLogger.Handle(se.Message);
MessageLog.MessageLog += messageTimeStamp + " : " + se.Message + "\n";
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
在OnDataReceived功能中,从服务器接收数据,需要更新数据以通过viewmodel属性MessageLog进行查看。 由于PropertyChanged为null,INofication不会引发事件。 但我正在贬值价值。
在viewmodel中读取此值并且它也通知属性调用,但属性更改为null,因此不会引发事件。
public void updateMesssage(string message)
{
App.Current.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, new Action(() =>
{
this.MessageLog.MessageLog += messageTimeStamp + " : <- " + message + "\n";
}));
}