我正在尝试使用MVVM创建UWP聊天。我不断收到此错误:
该应用程序调用了一个已编组为不同线程的接口
在这里我的视图模型中:
public void Notify(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
每当将值设置为绑定到xaml中TextBlock.Text属性的字符串属性时,就会发生此函数;
我尝试在视图模型中插入TextBlock(即vm已绑定到其text属性),并删除了xaml中的所有绑定并使用此功能:
private async Task LoadMessage(string sender, string message)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ChatBox += $"{sender}: {message} \n";
});
}
仍然相同,只是现在上面的函数中引发了异常。
我在寻找答案时发现了花药调度员,但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}" />
答案 0 :(得分:1)
解决方案:
所以要努力使聊天正常进行,这就是问题所在:
await CoreApplication.MainView
由于聊天与首页的视图不同,因此找不到绑定或xaml元素。
我的朋友意识到要在其他视图中进行更改,您需要获取其对象,因此,我们将此属性添加到了视图模型中:
public CoreApplicationView CurrentView { get; set; }
启动聊天室视图时,我们设置属性:
public UserViewModel userViewModel;
public ChatRoom(UserViewModel userViewModel)
{
this.InitializeComponent();
this.userViewModel = userViewModel;
userViewModel.ChatTbl = chatTbl;
userViewModel.CurrentView = CoreApplication.GetCurrentView();//this line
}
现在,当我们需要在视图中进行更改时,我们将使用:
_hubProxy.On<string, string>("SendMessage", async (sender, message) =>
{
await CurrentView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ChatTbl.Text += $"{sender}: {message} \n";
});
});
所以改为await CoreApplication.MainView
使用await CurrentView.CoreWindow
希望这会对我认识的人有所帮助
答案 1 :(得分:0)
您的LoadMessage
是一种异步方法,您无需将其放在Task.Run
中。您可以像下面这样直接调用它:
_hubProxy.On<string, string>("SendMessage", async (sender, message) =>
{
var result = await LoadMessage(sender, message);
});
如果必须将其放在Task.Run
中,可以这样称呼它:
_hubProxy.On<string, string>("SendMessage", async (sender, message) =>
{
var result = await Task.Run(async() => await LoadMessage(sender, message));
});