Интерфейс не обновляется при вызове в лямбда - PullRequest
0 голосов
/ 23 февраля 2020

Я использую библиотеку для управления светодиодами Yeelight . Я хочу добавлять кнопки в пользовательский интерфейс динамически / программно. Однако со следующим фрагментом никакие кнопки не добавляются (но я вижу печать консоли):

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>

Я подозреваю, что это связано с лямбда-областью, которая теряет доступ к пользовательскому интерфейсу. Или, может быть, из-за необходимости повторного рендеринга ... но я все еще потерялся. Я перепробовал много вещей. Спасибо

1 Ответ

0 голосов
/ 25 февраля 2020

Проблема в том, что библиотека вызывает OnDeviceFound в потоке без пользовательского интерфейса. Если вы хотите манипулировать пользовательским интерфейсом при возникновении события, вы должны перенаправить его в поток пользовательского интерфейса:

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
        }));
    });
}

Кроме того, вы должны позаботиться о том, чтобы обработчик событий никогда не вызывал исключение; вы можете не знать, как код, вызывающий событие, справится с ним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...