gpt4 book ai didi

mvvm - 如何在一个窗口中创建 VM 之间的 MVVM 父/子关系?

转载 作者:行者123 更新时间:2023-12-03 10:21:08 25 4
gpt4 key购买 nike

我正在开发一个一次性应用程序,但我喜欢利用这些机会来提高我对不熟悉事物的技能。所以我决定使用 MVVM 和 WPF,而不是坚持我的 WinForms 舒适区。我不知道如何让我的 UI 的某些部分相互通信。好吧,这更像是我找不到一种看起来不太可靠的方法。

应用程序测试一种算法的性能,该算法用于从大量收集数据中确定切片的最小值/最大值。 Here's what it looks like.

主窗口的 ViewModel 生成一个包含许多值的集合。我想为切片指定一个范围,然后执行几个版本的最小/最大算法来验证正确性和执行时间。

底部组框中的部分是 UserControl 的两个实例,我将其称为子控件。这对我来说很有意义,因为我知道我需要几个并且不想在主窗口中复制/粘贴集群。这就是问题发生的地方。

主窗口 VM 具有集合和切片范围的属性。我需要子虚拟机才能访问这些属性。事实证明这很困难。理想情况下,我想要这样的东西:

<local:AlgorithmTester RangeStart="{Binding RangeStart}"
RangeEnd="{Binding RangeEnd}"
Values="{Binding Values}" />

子 VM 有自己的 VM。如果我将依赖属性放在控件上,我还必须将这些属性链接到控件的 VM,可能通过代码内绑定(bind)。这对我来说似乎有点不可思议。我想到了以下替代方案,但对我来说似乎都很奇怪:
  • 不要使用用户控件;复制/粘贴每个测试人员的代码。
  • 在代码中为测试人员设置 VM,使 lambda 可以在闭包中捕获所需的属性。 (现在就这样做。)这让我觉得很脏,因为 lambdas 应该属于另一个类。
  • 一位 Twitter friend 建议使用事件聚合器。子虚拟机将订阅“RangeStartChanged”聚合事件(和其他事件)。我不喜欢这样,因为我觉得子虚拟机和父虚拟机之间的关系应该更清楚;也许它的旧习惯很难死?
  • 对具有适当属性的类使用模板化的 ItemsControl,而不是 UserControl。我仍然必须找到一种方法来传达主要 VM 属性中的更改,但这将是主 VM 内部的逻辑。我不喜欢这种方法的唯一原因是它让我觉得很奇怪。这可能是多年的 WinForms 经验让我望而却步。 (越想这个越喜欢。)

  • 还有其他解决方案吗?我对现有的那些太挑剔了吗?你会怎么办?

    最佳答案

    我会让您的 ParentViewModel 包含 ChildViewModel,并使用 DataTemplate 告诉 WPF 它应该使用 local:AlgorithmTester 绘制 ChildViewModel控制

    示例 View 模型

    public class ParentViewModel
    {
    // Actual implementation omitted for sake of simplicity
    public ChildViewModel TestViewModelA { get; set; }
    public ChildViewModel TestViewModelB { get; set; }
    }

    示例 XAML
    <Window>
    <Window.Resources>
    <!-- Data Template to tell WPF how to draw the ViewModels -->
    <DataTemplate DataType="{x:Type local:ChildViewModel}">
    <local:AlgorithmTester />
    </DataTemplate>
    <Window.Resources>

    <!-- Put ViewModels in ContentControls and let WPF figure out how to display them -->
    <UniformGrid Columns="2">
    <ContentControl Content="{Binding TestViewModelA}" />
    <ContentControl Content="{Binding TestViewModelA}" />
    </UniformGrid>
    </Window>

    您的算法属性(StartRange、EndRange 等)和方法(Calculate())存储在 ChildViewModel 中,而 AlgoritmTester 是使 ViewModel 用户友好的 View 。例如,它看起来像这样:
    <UniformGrid Columns="2" Rows="4">
    <TextBlock Text="Minimum:" />
    <TextBox Text="{Binding StartRange}" />
    <TextBlock Text="Maximum:" />
    <TextBox Text="{Binding EndRange}" />
    <TextBlock Text="Elapsed:" />
    <TextBox Text="{Binding Elapsed}" />
    <Button Content="Calculate" Command="{Binding CalculateCommand}" />
    </UniformGrid>

    编辑

    关于对上述问题的评论,您的 ParentViewModel 将负责将范围传递给 ChildViewModels。

    例如,如果范围是静态的,您可以在创建时设置它:
    TestViewModelA = new ChildViewModel();
    TestViewModelA.StartRange = 0;
    TestViewModelA.EndRange = 10;

    如果它是动态的,我会注册一个 PropertyChanged 事件处理程序来设置范围
    void ParentViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
    switch (e.PropertyName)
    {
    case "StartRange":
    TestViewModelA.StartRange = this.StartRange;
    TestViewModelB.StartRange = this.StartRange;
    break;
    case "EndRange":
    TestViewModelA.EndRange = this.EndRange ;
    TestViewModelB.EndRange = this.EndRange ;
    break;
    }
    }

    关于mvvm - 如何在一个窗口中创建 VM 之间的 MVVM 父/子关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6681954/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com