【发布时间】:2018-12-26 22:28:58
【问题描述】:
我正在尝试使用 MVVM 创建 UWP 聊天。我不断收到此错误:
应用程序调用了一个为不同线程编组的接口
在我的视图模型中:
public void Notify(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
每次将值设置为绑定到 xaml 中的 TextBlock.Text 属性的字符串属性时,都会发生此函数;
我尝试在视图模型中插入 TextBlock(vm 绑定到其文本属性)并删除 xaml 中的所有绑定并使用此功能:
private async Task LoadMessage(string sender, string message)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ChatBox += $"{sender}: {message} \n";
});
}
还是一样,只是现在在上面的函数中抛出了异常。
我在搜索答案时发现了 anther dispatcher,但似乎 uwp 无法识别它并用红色下划线标记它:
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//my code
});
我试过了:
await CoreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ChatBox += $"{sender}: {message} \n";
});
然后我得到了
非静态字段、方法需要对象引用
所以我创建了一个静态类来保存这个函数:
public static void UpdateTextBlock(TextBlock textBlock, string sender, string message)
{
textBlock.Text = $"{sender}: {message}";
}
并将其插入此调度程序。还是不行。仍然:需要一个对象引用...
我真的希望它是 MVVM,但任何可行的解决方案都是一种祝福。
编辑
今天我尝试回到绑定和 mvvm 模式。我将 LoadMessage 函数包装在这样的任务中:
private async Task<bool> LoadMessage(string sender, string message)
{
bool flag = false;
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
TextBindingProperty += $"{sender}: {message} \n";
flag = true;
});
return flag;
}
_hubProxy.On<string, string>("SendMessage", async (sender, message) =>
{
var result = await Task.Run(() => LoadMessage(sender, message));
});
仅在类中存在相同的异常:MyView.g.cs
在这个方法中:
public static void Set_Windows_UI_Xaml_Controls_TextBlock_Text(global::Windows.UI.Xaml.Controls.TextBlock obj, global::System.String value, string targetNullValue)
{
if (value == null && targetNullValue != null)
{
value = targetNullValue;
}
obj.Text = value ?? global::System.String.Empty; //in this line!!!
}
};
我的视图模型实现 INotifyPropertyChanged
public class UserViewModel : INotifyPropertyChanged
{
private string chatBox;
public string ChatBox
{
get { return chatBox; }
set { chatBox = value; Notify(nameof(ChatBox)); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
绑定到此属性的 xaml 元素如下所示:
<TextBlock Name="chatTbl" Text="{x:Bind userViewModel.ChatBox, Mode=TwoWay}" />
【问题讨论】:
-
而不是显示这些,只是向我们展示您的 ViewModel(全部,如果不是太大)现在的样子以及当前的错误是什么。另外,也显示 xaml 部分。
-
试一试:在加载消息中使用 CoreApplication.MainView..... 并将 PropertyChanged 包装在另一个任务中(不是 UI 任务)
-
@TheTanic 在 LoadMessage 中不是我做的吗? LoadMessage 返回任务,在其中我使用了 CoreApplication.MainView。将 propertyChanged 包装在另一个任务中是什么意思?你能显示代码吗?谢谢
-
@Muzib 我根据您的要求编辑了帖子
标签: c# multithreading mvvm binding uwp