我有一个绑定到的列表框List<T>
——这很好用。
我想让我的用户双击一个列表框项并打开一个新窗口,该窗口将显示该记录的“详细信息”视图。我希望这个新窗口数据绑定到与原始窗口上的列表框相同的集合。因为,该窗口有一个计时器,它轮询网络服务以获取更新的数据,我希望子(详细信息窗口)在主列表更新时也更新。
这很容易做到吗?一个例子会很好,但任何帮助表示赞赏!
我有一个绑定到的列表框List<T>
——这很好用。
我想让我的用户双击一个列表框项并打开一个新窗口,该窗口将显示该记录的“详细信息”视图。我希望这个新窗口数据绑定到与原始窗口上的列表框相同的集合。因为,该窗口有一个计时器,它轮询网络服务以获取更新的数据,我希望子(详细信息窗口)在主列表更新时也更新。
这很容易做到吗?一个例子会很好,但任何帮助表示赞赏!
您可以直接共享数据(即将 SelectedItem 引用传递给子窗口),但这无助于您管理跨多个窗口的行为和状态。如果它是只读视图,则问题不大,但是如果正在更改数据,它很快就会变得非常有问题。
这是使用模型视图的好处的一个很好的例子-?图案。MVVM通常是 WPF 的首选模式,因为 WPF 是为完全分离呈现而设计的。但是,在这种情况下,您可能需要更接近MVC(模型-视图-控制器)的东西,因为您确实希望协调不同 UI 元素之间的行为和状态。
我会推荐一种混合方法,我们称它为“MVVMC”只是为了让首字母缩写词更长更尴尬。实现一个完全与 UI 无关的 ViewModel,只公开数据和与数据相关的状态/行为——可能主要是 CRUD 类型的东西。然后实现一个特定于你的 UI 设计的控制器,它消耗和公开(通过委托或组合) 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,然后反转控制,以便控制器可以管理多窗口 UI。所以这里的控制器会将 ViewModel 作为 DataContext 注入到窗口(包括主窗口)中,以便于绑定。它还将绑定到主窗口上的事件,启动子窗口,并可能绑定到子窗口事件以正确管理它们(例如,每个子记录一个窗口,当主窗口关闭时关闭子窗口等)。
我会在这里更进一步,针对接口而不是 Window 实现控制器。这为您在重构方面提供了一些灵活性,但更重要的是,您可以针对模拟对控制器进行单元测试。
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
};