Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何为C#WPF中的用户控件集合设计基于页面的视图?_C#_Wpf_Xaml_Mvvm_Architecture - Fatal编程技术网

如何为C#WPF中的用户控件集合设计基于页面的视图?

如何为C#WPF中的用户控件集合设计基于页面的视图?,c#,wpf,xaml,mvvm,architecture,C#,Wpf,Xaml,Mvvm,Architecture,前言:用问题的形式来解释我的问题有点难,所以让我在下面解释一下 上下文:我正在开发一个音频混音器的用户界面(见图),作为其中的一部分,我有一行16个“通道条”(一个用户控件),每个都有一个音量控制器。但在模型中,混频器有32个通道(+辅助设备)。为了消除对带有滚动条的超大项控件的需要,我想实现一个页面系统,以切换模型中绑定UI的通道 用户界面的模型 在阅读了一些关于MVVM体系结构的示例之后,我将其缩小到了实现这一点的太多方法,但我对每种方法都有问题 将UI中的通道条直接绑定到ViewMode

前言:用问题的形式来解释我的问题有点难,所以让我在下面解释一下

上下文:我正在开发一个音频混音器的用户界面(见图),作为其中的一部分,我有一行16个“通道条”(一个用户控件),每个都有一个音量控制器。但在模型中,混频器有32个通道(+辅助设备)。为了消除对带有滚动条的超大项控件的需要,我想实现一个页面系统,以切换模型中绑定UI的通道

用户界面的模型

在阅读了一些关于MVVM体系结构的示例之后,我将其缩小到了实现这一点的太多方法,但我对每种方法都有问题

  • 将UI中的通道条直接绑定到ViewModel中的ObservableCollection,然后使用属性通知程序将其绑定到模型中的数据:
  • 
    
    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

    问题在于,这会为各个方向的属性更改创建大量事件处理程序,并最终在内存中创建一个音量控制器副本。所有这些对我来说似乎都是一个糟糕的设计,但这是我所看到的惯例,因为它允许模型与视图模型和视图完全分离,并且视图与模型之间没有直接联系

  • 直接绑定到模型的一部分,并在每次页面更改时使用ViewModel将UI频道条带重新绑定到不同的频道集。
    这似乎更合理,因为我没有创建不必要的数据和事件副本,并且可能会减少代码的混乱
  • 
    
    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并不是为了解决保存每个字节的难题,而是为了更好地进行分离、测试和主测试泰宁