0

Всем добрый день! Появилась следующая проблема, необходимо создать MenuControl, состоящий из XAML-разметки (стандартной)

<UserControl x:Class="ControlsLibrary.Views.MenuControl"
             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:vm="clr-namespace:ControlsLibrary.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
&lt;UserControl.DataContext&gt;
    &lt;vm:MenuControlViewModel/&gt;
&lt;/UserControl.DataContext&gt;

&lt;Grid/&gt;

</UserControl>

, MenuControl.cs (стандартный)

    public partial class MenuControl : UserControl
    {
        public MenuControl()
        {
            InitializeComponent();
        }
    }

и MenuControlViewModel.cs (пустой класс)

    public class MenuControlViewModel
    {
        public MenuControlViewModel(IMediator m)
        {}
    }

, при этом MenuControlViewModel должен быть задан как DataContext. Так же MenuControlViewModel должен иметь конструктор, принимающий экземпляр интерфейса IMediator в качестве параметра. Передачу в конструктор параметра сделал с помощью DependencyInjection:

private readonly IHost _host;
    public Register()
    {
        _host = Host.CreateDefaultBuilder()
            .ConfigureServices((hostContext, services) =&gt;
            {
                services.AddSingleton&lt;MainWindow&gt;();
                services.AddSingleton&lt;IMediator, Mediator&gt;();
            }).Build();
    }

    public void OnStartup(object sender, StartupEventArgs e)
    {
        using var serviceScope = _host.Services.CreateScope();
        var window = serviceScope.ServiceProvider.GetService&lt;MainWindow&gt;();
        window.Show();
    }

Во всём остальном коде DI работает. Но есть проблема: т.к. MenuControlViewModel должен быть DataContext, то нужно его где-то задать. Если задавать в XAML – будет ошибка, т.к. нельзя передать ничего в качестве параметра. Если задавать в MenuControl.cs, то нужно передать параметры в MenuControl.cs, Но будет ошибка – UserControl запускается только со стандартным конструктором, без параметров.

  • при этом MenuControlViewModel должен быть задан как DataContext - не должен, это нарушение MVVM, а также вообще проектирования в целом, ведь контролы должны быть универсальны и самостоятельны, а не зависеть от некого MenuControlViewModel. Вот задайте себе вопрос - простой TextBox просит от вас создание дополнительного класса для работы? Нет, он имеет органы управления (Text например), через который он и понимает, что выводить. А у вас, что будет если удалить этот класс? Запустится ли проект? Нет... – EvgeniyZ Oct 03 '21 at 19:04
  • @EvgeniyZ, то же самое можно сказать и про окна и страницы. Они не просят создания дополнительного класса для работы, но при этом если удалить класс окна или страницы, то проект тоже не запустится. – Vya4eslav5213 Oct 04 '21 at 03:34
  • Вы меня наверно не поняли. Ок, перефразирую... Все цвета, шрифты, анимации и др. - это View слой, этот слой не должен быть зависим от данных. Сами же данные, это Model слой (база, сайт, устройство, файлы и др.). Ну а связующий слой, тот, который берет из Model и предоставляет доступ для View - это ViewModel. Другими словами, тот же TextBox, у вас не должно быть, что внутри у него прописан свой DataContext из которого он читает текст, нет, он должен быть самостоятельны, со своим дизайном и дизайн-логикой, а данные, он берет из вне через привязку (<TextBox Text = "{Binding SomeText}">) – EvgeniyZ Oct 04 '21 at 06:07
  • Вы же сейчас делаете так, что он строго зависит от данных, от DataContect и прочего. Вот к примеру вам надо сделать тоже меню, но для других данных, у него будет другой VM класс (а-ля CustomMenuViewModel), что, будете делать еще один контрол, дублировать код, лишь чтоб изменить там данные? Ну согласитесь, что-то тут не то... Касательно окна - не путайте то, что вы задаете DataContext из вне (использование контрола) и то, что вы задаете его внутри (при реализации). – EvgeniyZ Oct 04 '21 at 06:13
  • @EvgeniyZ, я понял, спасибо большое! – Vya4eslav5213 Oct 04 '21 at 09:13
  • А если по простому - работает "viemodel first", то есть вы что-то меняете во вьюмоделях, а view через систему биндингов реагирует на это - создает и уничтожает контролы. Касательно вашего меню - контрол должен получать DataContext извне - явно или нет (задается в верстке) – vitidev Oct 04 '21 at 12:34

0 Answers0