首页 > 解决方案 > 在 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 范围有关。或者可能需要强制重新渲染..但我仍然迷路了。我尝试了很多东西。谢谢

标签: c#wpf

解决方案


问题是该库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
        }));
    });
}

此外,您应该注意事件处理程序永远不会抛出异常;您可能不知道引发事件的代码将如何处理它。


推荐阅读