如何为C#WPF中的用户控件集合设计基于页面的视图?
前言:用问题的形式来解释我的问题有点难,所以让我在下面解释一下 上下文:我正在开发一个音频混音器的用户界面(见图),作为其中的一部分,我有一行16个“通道条”(一个用户控件),每个都有一个音量控制器。但在模型中,混频器有32个通道(+辅助设备)。为了消除对带有滚动条的超大项控件的需要,我想实现一个页面系统,以切换模型中绑定UI的通道 用户界面的模型 在阅读了一些关于MVVM体系结构的示例之后,我将其缩小到了实现这一点的太多方法,但我对每种方法都有问题如何为C#WPF中的用户控件集合设计基于页面的视图?,c#,wpf,xaml,mvvm,architecture,C#,Wpf,Xaml,Mvvm,Architecture,前言:用问题的形式来解释我的问题有点难,所以让我在下面解释一下 上下文:我正在开发一个音频混音器的用户界面(见图),作为其中的一部分,我有一行16个“通道条”(一个用户控件),每个都有一个音量控制器。但在模型中,混频器有32个通道(+辅助设备)。为了消除对带有滚动条的超大项控件的需要,我想实现一个页面系统,以切换模型中绑定UI的通道 用户界面的模型 在阅读了一些关于MVVM体系结构的示例之后,我将其缩小到了实现这一点的太多方法,但我对每种方法都有问题 将UI中的通道条直接绑定到ViewMode
MainWindow.xaml
公共可观察收集音量控制器
{
获取{return\u faders;}
set{SetProperty(ref _faders,value);}
}
公共void Init()
{
//创建一个新的混合器
VMixer=新的混合器(32,8,8);
VMixer.MixChannels.CollectionChanged+=混合通道\u CollectionChanged;
}
//更多用于处理“MixChannel\u CollectionChanged”以及不同模型之间的更改的代码
ViewModel.cs
问题在于,这会为各个方向的属性更改创建大量事件处理程序,并最终在内存中创建一个音量控制器副本。所有这些对我来说似乎都是一个糟糕的设计,但这是我所看到的惯例,因为它允许模型与视图模型和视图完全分离,并且视图与模型之间没有直接联系
这似乎更合理,因为我没有创建不必要的数据和事件副本,并且可能会减少代码的混乱
MainWindow.xaml
public void UpdateFaderBindings(ChannelType faderMode,int faderModePage)
{
//[为简单起见省略代码]
对于(int i=0;i
ViewModel.cs
这两种体系结构显然都有各自的缺点,阅读数小时后,我无法确定在这种情况下正确的体系结构是什么。第一种解决方案肯定更合适,但我可能还会尝试通过在UI中创建两个单独的ItemsControl来避免所有处理程序(绑定到同一可见集合)第二个隐藏按钮和切换频道的按钮相互叠加,只需恢复两个项目控件的可见性。我以编写WPF机场值机系统为生,我一直以选择飞机座位的形式遇到这个问题。没有足够的空间来显示A380的所有525个座位,因此我不得不显示放置机身部分,让乘客滚动浏览。同样,值机柜台可能需要提供50种不同的航空公司供乘客选择,因此再次使用寻呼来滚动浏览 你真正想做的是实现一种形式的虚拟化。这反过来又需要视图逻辑。当你有不需要与实际GUI元素直接交互的视图逻辑时,正确的放置位置几乎总是在视图模型层。在商业应用程序中,这绝对是你需要的行为ant进行单元测试,但是如果没有GUI元素的实际存在,那么使用选项2就无法进行单元测试 选项#1看起来凌乱的原因是,尽管它更接近纯MVVM,但确实如此。您真正应该做的是在视图和视图模型之间创建1:1的关系。我个人会为每个混合器创建一个MixerServiceWModel类(可见或否)包含该混音器所需的信息,并维护当前可见信息的列表:
private IList<MixerViewModel> AllMixers;
public ObserveableCollection<MixerViewModel> VisibleMixers {get; set;} // would probably also need INPC
private-IList-AllMixers;
公共observeCollection访问混合器{get;set;}//可能还需要INPC
第一个列表适用于所有32个混音器,在启动时创建。第二个列表是当前可见的,只要当前页面发生更改,您就可以使用第一个列表中的元素填充该列表。这样做有助于完全分离关注点,使更改项目总数变得非常容易(全部或立即可见)现在,您还可以进行单元测试。是的,这意味着每当页面发生变化时,都会创建和销毁GUI项,但WPF就是这样设计的,只要您不过火,您的应用程序将保持响应速度。MVVM并不是为了解决保存每个字节的难题,而是为了更好地进行分离、测试和主测试泰宁