我有一个运行连续TCP读取操作的任务,当该读取操作从远程服务器读取JSON编码的消息时,它将向Command.cs类触发一个事件,在该类中它将处理原始JSON并将其转换为响应类,进行必要的检查,然后触发“完成”事件,最终客户端在该事件中订阅,他们可以接收可以添加到Observable集合的响应类。
我试图实现一个RaisePropertyChanged,该调用在Dispatcher上调用Invoke函数,该函数应正确更新ObservableCollection。
private static CancellationTokenSource cancellation;
private static event OnDataReceived datareceivedevent;
public static event OnDataReceived DataReceivedEvent
{
add
{
if(datareceivedevent == null)
{
datareceivedevent += value;
}
}
remove
{
datareceivedevent -= value;
}
}
private static async void ReadOperation(object t)
{
var token = (CancellationToken)t;
var stream = tcpClient.GetStream();
var byteBuffer = new byte[tcpClient.ReceiveBufferSize];
while (!token.IsCancellationRequested)
{
int lRead = 0;
if (stream.DataAvailable)
{
lRead = await stream.ReadAsync(byteBuffer, 0, byteBuffer.Length);
}
if (lRead > 0)
{
var response = ASCIIEncoding.ASCII.GetString(byteBuffer, 0, lRead);
datareceivedevent(response);
}
}
}
public static void StartReading()
{
Task.Factory.StartNew(ReadOperation, cancellation.Token, cancellation.Token);
}
上面的代码是一直运行到请求取消的任务。当数据可用时,它将转换为字符串并触发事件(如上所示)。
public event OnDataReceivedDeserialized OnDataReceivedDeserialized;
public bool Execute()
{
this.JSONFormat = ToJson();
TCPRequest.DataReceivedEvent += TCPRequest_DataReceivedEvent;
if (!JSONFormat.Equals(string.Empty))
{
return TCPRequest.SendToServer(this);
}
else
{
return false;
}
}
execute函数位于Command类中,该类处理将JSON发送到服务器所需的所有操作。该Command类预订TCPRequest datareceivedevent事件。
if (TCPRequest.IsConnected)
{
Command cmd = new Command();
cmd.RequestCommand = new Request(RequestType.info);
cmd.OnDataReceivedDeserialized += Cmd_OnDataReceivedDeserialized;
cmd.Execute();
}
public void Cmd_OnDataReceivedDeserialized(RequestResponse response)
{
LoPyList.Add(new LoPy() { name = "Test", id = "00" });
}
然后在其上方将创建用于预订命令事件的命令,服务器响应的值将到达该事件。
private ObservableCollection<LoPy> lopyList;
public ObservableCollection<LoPy> LoPyList
{
get { return lopyList; }
set {
lopyList = value;
RaisePropertyChangedEvent("LoPyList"); }
}
最后,上面是绑定到接口组合框的LoPyList。
<ComboBox Grid.Row="1" ItemsSource="{Binding Path=LoPyList}"
DisplayMemberPath="name"/>
我需要做的是ViewModel内部的函数更新LoPyList,并且可以在UI中查看它。
答案 0 :(得分:0)
事件触发时,您正在执行的操作是在ObservableCollection上调用“添加”方法:
LoPyList.Add(new LoPy() { name = "Test", id = "00" });
这里的问题是您的RaisePropertyChangedEvent
仅在设置LoPyList
属性时出现。当您调用Add()时,setter不会运行,因此RaisePropertyChangedEvent
不会被调用,绑定也不会被更新。
您可以做的是添加:
RaisePropertyChangedEvent("LoPyList");
调用Add()之后:
public void Cmd_OnDataReceivedDeserialized(RequestResponse response)
{
LoPyList.Add(new LoPy() { name = "Test", id = "00" });
RaisePropertyChangedEvent(nameof(LoPyList));
}
或者,ObservableCollection公开了一个CollectionChanged事件,
在添加,删除,更改,移动或刷新整个列表时发生。
您可以加入该事件,然后致电RaisePropertyChangedEvent("LoPyList");
答案 1 :(得分:0)
原来,我两次初始化了视图模型,并使用了未连接到视图的第二个视图模型。之后,我使用了调度程序,它的工作原理就像一种魅力。
感谢您的帮助!