gpt4 book ai didi

c# - 无法在 MVVM 中完成模式中介

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

我在 mvvm 中遇到中介模式问题

我将描述几乎所有类,以便更好地理解我的问题。

  • 我有它的 MainWindow 和 ViewModel,它非常简单,实际上除了持有我的一个 UserControl 之外什么都不做,ViewModel 中有一个 UserControl 属性绑定(bind)到 MainWindow 中的 ContentControl.Content。
  • 用户控件是相同的,每个控件中只有一个按钮,
    并且还有两个 ViewModel 带有处理 clikcs 的命令。
  • Class Mediator 是单调的,我尝试将它用于 ViewModel
  • 之间的迭代

    所以我想做的是在用户控件之间切换,而不是在 MainWindowViewModel 中创建它们和它们的 ViewModel。在我单击按钮后必须进行切换。例如,如果我单击 FirstUserControl 上的按钮,则 MainWindow 的 ContentControl 应切换到 SecondUserControl。

    问题出现在 UserControlsViewModels 中,我应该在 Mediator NotifyCollegue() 函数中将 UserControls 对象作为参数传递,但我无法访问它们
    (当然,这是 MVVM 的原理之一),这就是用户类型的问题,因为使用标准类型应该不成问题(例如传递 int 或 string...)。

    我在这里找到了这个解决方案
    http://www.codeproject.com/Articles/35277/MVVM-Mediator-Pattern

    以及为什么我不能在 MainWindowViewModel 中切换 UserControls,因为我希望 MainWindow 清除除当前 UserControl 绑定(bind)到 ContentControl 之外的所有内容。

    这个问题有什么可能的解决方案,我应该创建另一个单调类并在那里收集所有 userControls 引用并在 UserControlsViewModels 中使用它们,或者其他什么?

    我希望我已经清楚地描述了我的问题,并且有某种解决方案。

    我很乐意回答任何问题,非常感谢您的帮助!!!

    哦,那不是真正的应用程序,我只想了解 ViewModel 之间消息传递系统的想法(概念),而不是混合 ViewModel,而不是在其他 ViewModel 中创建 View 及其 ViewModel ...

    再次感谢!

    主视图
    <Window x:Class="TESTPROJECT.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TESTPROJECT"
    mc:Ignorable="d"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    Title="MainWindow" Height="500" Width="750">



    <Grid>
    <ContentControl Grid.Row="1" Content="{Binding PagesControl}"/>
    </Grid>

    主视图 View 模型
    namespace TESTPROJECT
    {
    class MainWindowViewModel : ViewModelBase
    {
    private UserControl _pagesControl;
    public UserControl PagesControl
    {
    //Property that switches UserControls
    set
    {
    _pagesControl = value;
    OnPropertyChanged();
    }
    get
    {
    return _pagesControl;
    }
    }

    public MainWindowViewModel()
    {
    //Method that will be listening all the changes from UserControls ViewModels
    Mediator.Instance.Register(
    (object obj) =>
    {
    PagesControl = obj as UserControl;
    }, ViewModelMessages.UserWroteSomething);
    }
    }
    }

    第一用户控件
    <UserControl x:Class="TESTPROJECT.FirstUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:TESTPROJECT"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
    <Button Command="{Binding GetCommand}">
    hello, i'm first user control!
    </Button>
    </Grid>

    FirstUserControl View 模型
    namespace TESTPROJECT
    {
    class FirstUserControlViewModel : ViewModelBase
    {
    //command that is binded to button
    private DelegateCommand getCommand;
    public ICommand GetCommand
    {
    get
    {
    if (getCommand == null)
    getCommand = new DelegateCommand(param => this.func(param), null);
    return getCommand;
    }
    }
    //method that will handle button click, and in it i'm sending a message
    //to MainWindowViewModel throug Mediator class
    //and that is allso a problem place because in theory i should
    //pass the opposite UserControl object , but from here i have no
    //acces to it
    private void func(object obj)
    {
    Mediator.Instance.NotifyColleagues(
    ViewModelMessages.UserWroteSomething,
    "PROBLEM PLACE");
    }
    }

    }

    第二用户控件
    <UserControl x:Class="TESTPROJECT.SecondUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:TESTPROJECT"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
    <Button Command="{Binding GetCommand}">
    Hello, i'm second user control!
    </Button>
    </Grid>

    SecondUserControl View 模型
    namespace TESTPROJECT
    {
    class SecondUserControlViewModel : ViewModelBase
    {
    //command that is binded to button
    private DelegateCommand getCommand;
    public ICommand GetCommand
    {
    get
    {
    if (getCommand == null)
    getCommand = new DelegateCommand(param => this.func(param), null);
    return getCommand;
    }
    }
    //method that will handle button click, and in it i'm sending a message
    //to MainWindowViewModel throug Mediator class
    //and that is allso a problem place because in theory i should
    //pass the opposite UserControl object , but from here i have no
    //acces to it
    private void func(object obj)
    {
    Mediator.Instance.NotifyColleagues(
    ViewModelMessages.UserWroteSomething,
    "PROBLEM PLACE");
    }
    }

    }

    类调解员

    枚举 ViewModelMessages
    namespace TESTPROJECT
    {
    //this enum holding some kind of event names fro example UserWroteSomething
    // is a name of switching one UserControl to another
    public enum ViewModelMessages { UserWroteSomething = 1 };

    class Mediator
    {
    //Singletone part
    private static Mediator instance;
    public static Mediator Instance
    {
    get
    {
    if (instance == null)
    instance = new Mediator();
    return instance;
    }
    }
    private Mediator() { }
    //Singletone part

    //collection listeners that holds event names and handler functions
    List<KeyValuePair<ViewModelMessages, Action<Object>>> internalList =
    new List<KeyValuePair<ViewModelMessages, Action<Object>>>();


    //new listener registration
    public void Register(Action<object> callBack, ViewModelMessages message)
    {
    internalList.Add(
    new KeyValuePair<ViewModelMessages, Action<Object>>(message, callBack));
    }

    // notifying all the listener about some changes
    // and those whose names fits will react
    public void NotifyColleagues(ViewModelMessages message, object args)
    {
    foreach(KeyValuePair<ViewModelMessages, Action<Object>> KwP in internalList)
    if(KwP.Key == message)
    KwP.Value(args);
    }
    }

    }

    应用起点
        public partial class App : Application
    {
    private void Application_Startup(object sender, StartupEventArgs e)
    {
    FirstUserControl first = new FirstUserControl() { DataContext = new FirstUserControlViewModel() };
    SecondUserControl second = new SecondUserControl() { DataContext = new SecondUserControlViewModel() };

    new MainWindow()
    {
    DataContext = new MainWindowViewModel() { PagesControl = first }
    }.ShowDialog();
    }
    }

    最佳答案

    如果我对您的理解正确,当当前事件 View 模型上发生特定操作(例如,您按下按钮)时,您希望导航到另一个 View (或分别为 View 模型)。

    如果你想为此使用你的中介,你可以像这样构造它:

    public class Mediator
    {
    // These fields should be set via Constructor Injection
    private readonly MainWindowViewModel mainWindowViewModel;
    private readonly Dictionary<ViewModelId, IViewFactory> viewFactories;

    public void NotifyColleagues(ViewModelId targetViewModelId, ViewModelArguments arguments)
    {
    var targetFactory = this.viewModelFactories[targetViewModelId];
    var view = targetFactory.Create(viewModelArguments);
    this.mainWindowViewModel.PagesControl = view;
    }

    // other members omitted to keep the example small
    }

    然后,您将为每个 View - View 模型组合创建一个工厂。与 ViewModelArguments ,您可以将来自其他 View 模型的信息传递到新创建的 View 模型中。 ViewModelId 可以像您的 ViewModelMessage 一样是一个简单的枚举,您也可以使用 Type的 View 模型(我会建议你去追求)。

    此外,我建议您不要在 Mediator 上使用私有(private)构造函数。类,因为否则您无法传入 mainWindowViewModel 和 View 工厂的字典。您应该能够在您的应用程序启动方法中配置它。

    另外,请注意,还有许多其他方式来构建 MVVM 应用程序,例如使用数据模板来实例化 View 模型的 View - 但我认为这对于你的小例子来说有点太牵强了。

    关于c# - 无法在 MVVM 中完成模式中介,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37103296/

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