【问题标题】:WPF await variable change then Update UIWPF 等待变量更改然后更新 UI
【发布时间】:2017-02-18 00:20:39
【问题描述】:

假设我有一个类通过 TCP 流接收数据,对其进行解析并相应地更改其属性。

public static class SomeClass
{
    static bool myBool;
    static string myMessage;

    public static void ToggleBool()
    {
        myBool = !myBool;
        // Do some other stuff here
    }

    public static UpdateMessage(string message)
    {
        System.Diagnostics.Debug.WriteLine(message);
        ProcessMessage(message);
        myMessage = message;
    }
}

现在我想做的是有一个 WPF“调试窗口”,它将直观地显示设置。我想基本上运行一个循环来相应地更新窗口的某些部分。

类似:

public partial class LogWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public Async Task UpdateUI()
    {
        while(checkForUpdates)
        {
            myCheckbox.IsChecked = await SomeClass.UpdatedBoolValue();

            string newMessage = await SomeClass.NewMessageRCVD();
            txtBox.Append(newMessage);
        }
    }
}

但这有两个明显的问题。一,我不知道如何通过不断地检查while循环来制作一个不会烧毁CPU的函数。我想我可以使用 getter/setter 方法。第二,我必须更新两者才能再次运行该循环。

最好的方法是什么?如何只更新 UI 中需要更新的部分?

编辑:类似问题:Write an Async method that will await a bool

【问题讨论】:

  • 使用定时器在一定的时间间隔内更新所有值。
  • 如果您使用 Caliburn Micro 或 ReactiveUI,它们都有一些用于应用内消息分发的 pub-sub 实现,正好解决了这些问题。

标签: c# wpf


【解决方案1】:

取决于实现的复杂程度/您的需求。

从您的示例中,如果您让 SomeClass 实现 INotifyPropertyChanged,您可以轻松地将 WPF 窗口附加到它,并且通过绑定窗口将自动更新而没有任何形式的循环。

如果您谈论多个类并且希望它们都在同一个窗口中显示属性信息,那么您最好的选择可能是创建一个队列。在您希望跟踪的每个属性中,让 setter 写入队列。 (全局或单例)然后您可以轻松地在窗口中显示该信息,或通过Observer pattern 显示多个。也可以将其设置为从不写入生产中的队列,或者使用条件编译语句,如果您愿意,生产甚至不会有代码。

【讨论】:

  • 谢谢!想通了,并用一些示例代码输入了一个答案,以帮助其他人开始,但你也有一些很好的信息在这里。
【解决方案2】:

最好的方法是使用数据绑定。

所以我们需要首先定义我们的数据来自哪里。这称为上下文。这将来自一个 ViewModel,它是一个 MVVM 术语。如果您不了解 MVVM,请不要担心,这可能来自您拥有的任何课程。在后端 .xaml.cs 代码中,我们需要将该类添加到我们的 Windows 的 DataContext。看起来是这样的:

public partial class DebugView : Window
{
    public DebugView()
    {
        InitializeComponent();
        DataContext = new DebugViewModel();
    }
}

在我们的 WPF 窗口 XAML 文件中,我们将有一个标签和文本框,其定义如下:

<Label Content="{Binding ClientCount, FallbackValue='Clients: 00'}" ... />
<TextBox Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}" ... />

标签的文本是它的“内容”,而文本框的文本只是“文本”。我们在其中添加绑定关键字,现在每个文本将分别链接到变量ClientCountPort。所以我们的DebugViewModel 类一开始会是这样的:

    private string _ClientCount;
    public string ClientCount
    {
        get { return _ClientCount; }
        set { _ClientCount= value; RaisePropertyChanged("ClientCount"); }
    }
    private string _Port;
    public string Port
    {
        get { return _Port; }
        set { _Port= value; RaisePropertyChanged("Port"); }
    }

现在你没有一个名为RaisePropertyChanged() 的函数,所以我所做的(我认为这是常见的做法)是我创建了一个基类来实现INotifyPropertyChanged 并处理那里的所有工作。

所以我们的基类BaseViewModel 将继承自INotifyPropertyChanged 类,并为我们设置一切。看起来像这样(随意复制粘贴并按原样使用):

using System.ComponentModel;

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    internal void RaisePropertyChanged(string prop)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
    }

   // Other functions we want all ViewModels to have
}

那么我们的DebugViewModel 类将如下所示:

public class ServerViewModel : BaseViewModel
{
    private string _ClientCount;
    public string ClientCount
    {
        get { return _ClientCount; }
        set { _ClientCount= value; RaisePropertyChanged("ClientCount"); }
    }
    private string _Port;
    public string Port
    {
        get { return _Port; }
        set { _Port= value; RaisePropertyChanged("Port"); }
    }

    public DebugViewModel()
    {
        // Initialize to default values
        ClientCount = $"Clients {server.clientCount}";
        Port = $"{server.port}";
    }

    // Rest of code
}

然后,当您启动程序时,它将自动填充字段,当您更改文本框中的数据时,字符串将更改,反之亦然。我们 XAML 声明的 UpdateSourceTrigger=PropertyChanged 部分使得一旦文本框中的数据发生更改,变量就会立即更新(默认行为是文本框失去焦点时。例如,您切换到下一个文本框或单击离开)。

这非常酷,因为您可以在输入时动态验证输入,并且不必担心切换到 UI 线程来更新 UI,而且 IMO 只需像这样绑定代码就可以让代码看起来更简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 2020-11-10
    相关资源
    最近更新 更多