2009-10-28 94 views
0

我是WPF的新手,并且遇到了一个小项目的问题。我正在构建一个测试器来模拟受UDP控制的设备。我有几个实现UDP作为异步实现的类。我有主窗口代码隐藏轮询接收缓冲区的数据和更新。它工作,但非常笨重。所以我移动了EndReceiveFrom所在的异步接收中的所有代码。它速度更快,摆脱投票。但我无法再访问窗口控件来更新它们。从非窗口类访问WPF控件

如何从窗口外部访问控件?该窗口实例化运行它的UDP类,所以我可以在构造函数调用上传递事物。当然,我可以访问应用程序。我知道我在这里错过了一些东西。

理查德

+0

http://stackoverflow.com/questions/3373471/how-get-control-from-non-window-class-in-wpf – Eldar 2010-07-30 16:48:53

回答

2

已经有一段时间 - 所以我不会提供太多的代码块 - 但听起来好像你可能要应用MVC,或者其堂兄弟MVP和MVVM。不要太担心他们的立场,但一般来说,他们试图定义View [你的窗口],Data [你网络层的结果]和Business [你的网络层]之间的关系。

就你而言,我会推荐MVVM。如果你使用Google,你应该能够找到关于设计模式的大量信息以及应用它的方法。再次,不要过多地理论这个理论。只是一个fyi。

下,一些肉,

从概念上讲,有“数据”您希望在“查看”来表示。不用担心视图,我们首先封装你的数据。

// name is a little too general, so just rename it to something 
// specific in your source. 
public class NetworkViewModel 
{ 
    // enumerate your data here 
    public int Trouble { get; set; } 
    public int Tribbles { get; set; } 
    ... 
} 

您的意见是你的视窗。有您的视图实例化XAML中,绑定该“视图模型”

public class MyNetworkMonitor 
{ 
    ... 
    // advanced: if you were injecting this - say from another source 
    // or intended to replace the instance during runtime, there are 
    // ways to deal with that. for now, we presume one instance for 
    // application lifetime. 
    public NetworkViewModel ViewModel { get; set; } 
    public MyNetworkMonitor() 
    { 
     ViewModel = new NetworkViewModel(); 
    } 
    ... 
} 

和一个实例属性

// Xaml omitted, a limit to my memory :P 
// but just regular binding to say ViewModel.Trouble 

好吧。所以如果你的视图模型有一个初始值,它会显示给绑定控件。不幸的是,如果视图模型属性更新,则无法告诉绑定控件的值已更改。呃,当然,除非你实现了一个通用的接口,WPF绑定寻找,

public class NetworkViewModel : INotifyPropertyChanged 
{ 
    // defined by interface 
    public event PropertyChangedEventHandler PropertyChanged; 
    private int _trouble = 0; 
    public int Trouble 
    { 
     get { return _trouble; } 
     set 
     { 
      // 1. if value changes 
      if (_trouble != value) 
      { 
       _trouble = value; 
       // 2. inform whomever is listening! 
       if (PropertyChanged != null) 
       { 
        PropertyChanged (
         this, 
         new PropertyChangedEventArgs ("Trouble")); 
       } 
      } 
     } 
    } 
} 

当然,你可以用和任何你喜欢缓解语法做些什么,而preceeds是您的裸机上执行模型方面。

如果您要处理窗口中的按钮并增加ViewModel.Trouble,您会在绑定控件中看到实时更新。好哇!

所有剩下的事情就是将您的业务层(即您的网络层)连接到ViewModel。你可以通过很多方式来做到这一点。您可以将视图模型的实例传递给网络层,您可以让视图模型直接响应网络层上的事件 - 这完全取决于您。

现在,如果你继续这样做,它将无法正常工作。抱歉。现在,这不完全是我的错,你看Wpf不喜欢任何人修改其数据。更具体地说,任何可能影响Wpf控件的东西必须在拥有该控件的Gui线程上调用。正如你可能猜到的那样,你用来修改视图模型的线程来自网络中断和什么。网络线程。 Pleabs。 MorlocksPah

无论如何,我离题了。有一个相对无痛的解决方法。当您检测到想要报告的更改时,请将更改发送到Gui线程。

someWpfControl.Dispatcher.Invoke (
    DispatcherPriority.Normal, 
    new Action(
    delegate() 
    { 
     ViewModel.Trouble = someNewValue; 
    }); 

但这是有点没用,因为你的网络层不应该知道任何有关Wpf。所以如何在ViewModel内如何与之前一样,随意将其包装在其他地方。就像在辅助方法中一样。顺便说一句,'someWpfControl'可以是窗口。所以你可以把它传给ctor。我也强烈建议你谷歌替代“调用调度员”,因为可能有更聪明的方法,这样做不涉及控制参考,广泛剪切和粘贴在你的视图模型,或其他任何。

正如只要GUI线程更新的控制,你可以做任何你想做:)

而且,我的队友和WPF弟子肯特谁知道无穷多个有关WPF比我无耻插头。 [http://kentb.blogspot.com/]

干杯:)

+0

顺便说一句,你最好的WPF资源1.)谷歌,和2.)Wpf释放[一本书]。搏一搏 :) – 2009-10-28 16:37:49