我有一个绑定(bind)到 List<T> 的列表框-- 这很好用。
我想让我的用户双击一个列表框项目并打开一个新窗口,该窗口将显示该记录的“详细信息” View 。我希望这个新窗口数据绑定(bind)到与原始窗口上的列表框相同的集合。因为,那个窗口有一个计时器,它轮询一个 webserivce 更新数据,我希望子(详细信息窗口)在主列表更新时也更新。
这很容易做到吗?一个例子会很好,但我们将不胜感激!
请您参考如下方法:
您可以直接共享数据(即将 SelectedItem 引用传递给子窗口),但这并不能帮助您跨多个窗口管理行为和状态。如果它是一个只读 View ,那么问题不大,但如果数据正在更改,它很快就会变得非常有问题。
这是一个很好的例子,说明了使用 Model-View-?图案。 MVVM通常是 WPF 的首选模式,因为 WPF 是为完全分离表示而设计的。但是,在这种情况下,您可能需要更接近 MVC 的值。 (模型- View - Controller ),因为您确实想要协调不同 UI 元素之间的行为和状态。
我会推荐一种混合方法,我们称它为“MVVMC”只是为了让首字母缩略词更长更难看。实现一个完全与 UI 无关的 ViewModel,并且只公开数据和数据相关的状态/行为——可能主要是 CRUD 类型的东西。然后实现一个特定于您的 UI 设计的 Controller ,它使用和公开(通过委托(delegate)或组合)ViewModel,但进行封装。所有的多窗口显示行为——每个项目强制一个窗口,传播关闭请求等。
public class MyViewModel : INotifyPropertyChanged, INotifyCollectionChanged
{
public MyViewModel(DataModel dataModel) { ... }
}
public class MyController
{
public MyController(MainWindow mainWindow, ViewModel viewModel) { ... }
public ViewModel { get { return _viewModel; } }
public ICommand DisplayChild { ... }
}
所以您真正要做的是采用 MVVM,然后反转控制,以便 Controller 可以管理多窗口 UI。所以这里的controller会将ViewModel作为DataContext注入(inject)到windows(包括main)中,方便绑定(bind)。它还将绑定(bind)到主窗口上的事件,启动子窗口,并可能绑定(bind)到子窗口事件以便正确管理它们(例如,每个子记录一个窗口,在主窗口关闭时关闭子窗口等)。
我会在这里更进一步,针对接口(interface)而不是 Window 实现 Controller 。这为您在重构方面提供了一定的灵 active ,但更重要的是,您可以根据模拟对 Controller 进行单元测试。
public interface IControllerChild
{
public void Show();
public bool Activate();
public void Close();
// add other behaviors here
}
public class DetailWindow : Window, IControllerChild
{
// implement other behaviors here
}
public class MockControllerChild : IControllerChild
{
public void Show() { IsShowing = true; ActionLog.Add(MockControllerAction.Show); }
public void Activate() { IsShowing = false; ActionLog.Add(MockControllerAction.Activate); }
public void Close() { IsShowing = false; ActionLog.Add(MockControllerAction.Close); }
public bool IsShowing { get; private set; }
public IList<MockControllerAction> ActionLog { get; private set; }
// mock and record other behaviors here
}
public enum MockControllerAction
{
Show,
Activate,
Close,
// Add other behaviors here
};
