【问题标题】:automatic open new window without timer WPF没有定时器WPF自动打开新窗口
【发布时间】:2014-10-17 23:11:40
【问题描述】:

我需要帮助解决一些问题。在 MainWindow WPF 中,我从设备读取状态,0 是正常工作,1 是其他状态。我想在获得状态 = 1 时打开新窗口,并在获得 0 时关闭它。我尝试使用计时器和 showDialog 来完成。新窗口已创建,但 MainWindow 中的状态不会改变,直到我手动关闭新窗口。任何建议如何在没有计时器的情况下做到这一点?也许一些样本。

提前致谢。

MainWindow - 计时器滴答声:

public void t1_Tick(Object Sender, EventArgs e)
{
    HttpWebRequest request7 = WebRequest.Create("http://localhost:8080/datasnap/rest/TAutomatServerMethods/uCard") as HttpWebRequest;

    using (HttpWebResponse response7 = request7.GetResponse() as HttpWebResponse)
    {

        StreamReader reader7 = new StreamReader(response7.GetResponseStream());

        string json7 = reader7.ReadToEnd();

        //  MessageBox.Show(json);

        JObject o7 = JObject.Parse(json7);
        int status_int = Convert.ToInt32(o7["result"][0]);

        if (status_int == 1)
        {
            uCard uc1 = new uCard();
            uc1.ShowDialog();
        }
}

Window1 - 关闭窗口

public void t1_Tick(Object Sender, EventArgs e)
{

    if (MainWindow.status_int == 0 )
    {
        this.Close();
    }
}  

【问题讨论】:

  • 这里为什么有定时器?那是检查变量吗?我觉得缺少一些代码。 “MainWindow”中的什么状态没有改变?顺便一提; ShowDialog 将阻塞正在执行的线程,直到它被关闭。
  • 这就是为什么,因为我不知道如何在没有计时器的情况下做到这一点。是的,window1 中的计时器检查主窗口中的状态。
  • 我同意需要更多上下文。关于 ShowDialog 的说明:它本身不会阻塞线程。窗口消息仍然被抽出,UI 仍然可以绘制。这些是在 ShowDialog 方法的上下文中发生的事情。但是被阻塞的是调用方法的执行;该方法(此处为“t1_Tick”)不会返回 - 甚至不会继续执行 - 直到 ShowDialog 方法返回,直到关闭对话框窗口才会发生。
  • 由什么函数更新?是什么导致该函数执行?您确定在显示其他窗口时它能够执行吗? “status_int 在同一个计时器方法中......”是什么意思?对我来说,这意味着它是一个局部变量。但如果它是一个局部变量,你希望其他线程如何检查它?最后,如果它不是局部变量而是真正在线程之间共享,您是否将其标记为 volatile 以确保执行的代码始终看到当前值?请注意,如果您发布了足够多的代码,则不需要回答所有这些问题。
  • @user3455769:无意冒犯,但该回复并未解决我实际提出的任何问题。 :(

标签: c# wpf timer


【解决方案1】:

首先,您需要创建一个事件以在值更改时引发:

public event Action<int> StatusChanged;

还有一个属性在它改变时提升它:

//This is very close to a standard INotifyPropertyChanged
private int status_int = 0;
private int Status
{
    get { return status_int; }
    set
    {
       if (Status != value)
       {
           status_int = value;
           StatusChanged(value);
       }
    }
}

摆脱计时器中的状态int检查,只需设置变量:

Status = retrieved_status;

报名参加:

public MainWindow()
{
    StatusChanged += HandleStatusChange;
}

和你的“ShowDialog”传递表单的实际实例

private void HandleStatusChange(int newValue)
{
    if (newValue == 1)
    {
       //Threaded so we don't hang the timer callback
       new Thread(() =>
       {
          uCard uc1 = new uCard(this);
          uc1.ShowDialog();
       }).Start();
    }
}

然后在您的弹出窗口中,您的构造函数将是:

public uCard(MainWindow window)
{
    window.StatusChanged += CheckForClose;
}

您将摆脱那个计时器并拥有:

private void CheckForClose(int newValue)
{
    if (newValue == 0 )
    {
      this.Close();
    }
}

它仍然很糟糕,但更清洁和可维护。更重要的是,它确实会起作用。

【讨论】:

  • 感谢@BradleyDotNET :)
  • 在 uCard 窗口中我得到:PresentationCore.dll 中发生了“System.InvalidOperationException”类型的未处理异常“调用线程必须是 STA,因为许多 UI 组件都需要这个”
  • @user3455769 然后将它标记为 STA,无论它抱怨哪个线程。我不确定为什么其中任何一个都需要是 STA,但它不会伤害你。
  • 好的。现在工作正常。再次感谢 BradleyDotNET。
猜你喜欢
  • 1970-01-01
  • 2017-08-26
  • 2015-03-03
  • 2014-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多