c# - 在 lambda 中调用时 UI 未更新
问题描述
我正在使用库来控制 Yeelight LED。我想以动态/编程方式向 UI 添加按钮。但是,使用以下代码段,没有添加任何按钮(但我看到了控制台打印):
private readonly Yeelights _yee = new Yeelights();
private void btnAddMore_Click(object sender, RoutedEventArgs e) {
Button newBtn = new Button {Content = "A New Button"};
splMain.Children.Add(newBtn); // button is added
_yee.discover((o, args) => {
Console.WriteLine(args.Device.Hostname); // it prints
Button newBtn2 = new Button {Content = args.Device.Hostname.ToString()};
splMain.Children.Add(newBtn2); // NO button is added
});
}
方法代码discover
:
public void discover(DeviceLocator.DeviceFoundEventHandler deviceFound) {
DeviceLocator.OnDeviceFound += deviceFound;
DeviceLocator.Discover();
}
用户界面 XAML:
<Window x:Class="my_lights.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AddControls" Height="114" Width="212">
<StackPanel Name="splMain">
<Button Click="btnAddMore_Click">Discover</Button>
</StackPanel>
</Window>
我怀疑这与无法访问 UI 的 lambda 范围有关。或者可能需要强制重新渲染..但我仍然迷路了。我尝试了很多东西。谢谢
解决方案
问题是该库OnDeviceFound
在非 UI 线程中引发了 。如果要在引发事件时操作 UI,则必须将其编组到 UI 线程:
private void btnAddMore_Click(object sender, RoutedEventArgs e) {
Button newBtn = new Button {Content = "A New Button"};
splMain.Children.Add(newBtn); // button is added
_yee.discover((o, args) => {
BeginInvoke((Action)(() => {
Button newBtn2 = new Button {Content = args.Device.Hostname.ToString()};
splMain.Children.Add(newBtn2); // NO button is added
}));
});
}
此外,您应该注意事件处理程序永远不会抛出异常;您可能不知道引发事件的代码将如何处理它。
推荐阅读
- algorithm - 防止二维网格旅行者重复的最小数据结构
- c - C动态分配结构数组及其组件
- dart - 在 Dart 中,如何在 stdin.readLineSync() 创建的输入之前添加“>>”?
- javascript - 如何在使用 jQuery 单击特定链接时切换到特定选项卡面板?
- jquery - 如何在 jquery 属性中使用正则表达式?
- c++ - 什么是自定义点对象以及如何使用它们?
- android - 有关通过 android 设备在应用程序上显示单击图像的问题
- java - 如何转换 PCollection
java 内存集合中只有一个元素? - php - 在环境托管工作时出现代码错误
- c# - 具有重复项的 LINQ 联合