0

У меня есть ItemsVM при нажатии на элемент я обрабатываю его в нем ClickHandler. Дальше я хочу открыть новое окно в зависимости от элемента. При обработке нажатия, я получаю из бд некоторую информацию(допустим Id). Дальше нужно как-то передать в ElementVM Id и создать Page(или datatemplate). Очевидно что нужно поменять VM c ItemsVM на ElementVM. Принцип похожий как гиперссылки в браузере, мы нажимаем на ссылку нам выдает новую страницу. В CodeBehind все пусто. Это вакуумный код для понимания.

Если у вас есть свои реализации или предложение отправляйте

MainWindows.xaml

<Grid Margin="0,0,0,-3" Background="#FFC8E4FF">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
    &lt;ListView Grid.ColumnSpan=&quot;2&quot; Margin=&quot;117,70,0,0&quot; Background=&quot;{x:Null}&quot; ItemsSource=&quot;{Binding GetItems}&quot;
     ScrollViewer.VerticalScrollBarVisibility=&quot;Disabled&quot; ScrollViewer.HorizontalScrollBarVisibility=&quot;Disabled&quot; Width=&quot;248&quot; FontSize=&quot;22&quot; HorizontalContentAlignment=&quot;Center&quot; VerticalAlignment=&quot;Top&quot; HorizontalAlignment=&quot;Left&quot; BorderBrush=&quot;#FF2558F0&quot; FlowDirection=&quot;RightToLeft&quot; VerticalContentAlignment=&quot;Center&quot; Height=&quot;373&quot;        
              &gt;

        &lt;ListView.DataContext&gt;
            &lt;vm:ItemsVM&gt;&lt;/vm:ItemsVM&gt;
        &lt;/ListView.DataContext&gt;

        &lt;ListView.ItemTemplate&gt;
            &lt;DataTemplate&gt;
                &lt;Grid Height=&quot;118&quot; Width=&quot;226&quot; Background=&quot;#FF9C9C9C&quot; HorizontalAlignment=&quot;Left&quot; &gt;
                    &lt;Grid.InputBindings&gt;
                        &lt;MouseBinding Gesture=&quot;LeftClick&quot;
                                     Command=&quot;{Binding DataContext.DelegateCommands,
                                     RelativeSource={RelativeSource AncestorType=ListView}}&quot;
                                     CommandParameter=&quot;{Binding}&quot;&gt;
                        &lt;/MouseBinding&gt;
                    &lt;/Grid.InputBindings&gt;




                    &lt;Label Content=&quot;{Binding Name}&quot; Width=&quot;Auto&quot; Height=&quot;Auto&quot; Margin=&quot;16,10,10,68&quot;  Background=&quot;#FFEDFFD6&quot; FontSize=&quot;20&quot; HorizontalContentAlignment=&quot;Center&quot; VerticalContentAlignment=&quot;Center&quot;/&gt;
                    &lt;Label Content=&quot;{Binding Id}&quot; Width=&quot;Auto&quot; Height=&quot;Auto&quot; Margin=&quot;62,60,63,10&quot;  FontSize=&quot;20&quot; Background=&quot;#FFF4FFD6&quot; VerticalAlignment=&quot;Stretch&quot; HorizontalContentAlignment=&quot;Center&quot; VerticalContentAlignment=&quot;Center&quot; /&gt;

                &lt;/Grid&gt;
            &lt;/DataTemplate&gt;
        &lt;/ListView.ItemTemplate&gt;
    &lt;/ListView&gt;
&lt;/Grid&gt;

ItemsVM.cs

  class ItemsVM : ViewModel
    {
        public ICommand DelegateCommands { get => _DelegateCommands; }
    private ICommand _DelegateCommands;

    /// &lt;summary&gt;
    ///  обработка нажатия
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;
    public void ClickHandler(dynamic e)
    {
        int id = e.Id;
        string name = e.Name;

        // Дальше делаю SELECT из бд и получаю подробную информацию

    }
    /// &lt;summary&gt;
    /// Получаю коллекцию элементов для отображения и делаю binding
    /// &lt;/summary&gt;
    public ObservableCollection&lt;Item&gt; GetItems
    {
        get
        {
           return new ObservableCollection&lt;Item&gt;{ new Item(&quot;A&quot;,1), new Item(&quot;B&quot;,2), new Item(&quot;C&quot;,3) };
        }
    }
    public ItemsVM()
    {
        _DelegateCommands = new DelegateCommand(o =&gt; ClickHandler(o));
    }
}

Item.cs

 class Item
    {
        public string Name { get; set; }
        public int Id { get; set; }
    public Item()
    {

    }
    public Item(string name,int id)
    {
        Name = name;
        Id = id;
    }
}

ViewModel.cs

 abstract class ViewModel : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add
        {

        }
        remove
        {

        }
    }



    protected void OnPropertyChanged([CallerMemberName] string propertyName = &quot;&quot;)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    protected virtual bool Set&lt;T&gt;(ref T field, T value, [CallerMemberName]string PropertyName = null)
    {
        if (Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(PropertyName);
        return true;
    }
    private bool _Disposed;
    public void Dispose()
    {
        Dispose(true);
    }
    public void Dispose(bool Disposing)
    {
        if (!Disposing || _Disposed) return;
        _Disposed = true;
    }
}

DelegateCommand.cs

  class DelegateCommand : ICommand
    {
    Action&lt;object&gt; execute;
    Func&lt;object, bool&gt; canExecute;


    public event EventHandler CanExecuteChanged;


    public DelegateCommand(Action&lt;object&gt; execute, Func&lt;object, bool&gt; canExecute)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public DelegateCommand(Action&lt;object&gt; execute)
    {
        this.execute = execute;
        this.canExecute = this.AlwaysCanExecute;
    }

    public DelegateCommand()
    {

    }

    public void Execute(object param)
    {
        execute(param);
    }

    public bool CanExecute(object param)
    {
        return canExecute(param);
    }


    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }


    private bool AlwaysCanExecute(object param)
    {
        return true;
    }


}

  • Вы много делаете лишних действий, местами даже нарушаете MVVM. Ну а по вопросу - я немного не понял что вы хотите, открыть новое окно с нужными данными, или внутри одного окна сменить содержимое? И то и много раз обсуждалось тут, на SO. – EvgeniyZ Sep 24 '21 at 18:48
  • @EvgeniyZ ну мне это надо в одном окне, в интернете не находил, то как я хотел сделать. Думал что это ситуация достаточно распространенная. А делать одну VM для обработки всего это не правильно, разве нет? – zelberman Sep 24 '21 at 20:17
  • 2
    Кто сказал про одну VM? Правила SOLID не отменяли вроде, SRP - одна задача = один метод/класс. Также и тут, все по своим M, VM и V. Вот самый простой (и лучший) вариант отображение разного содержимого, а вот почему page это не MVVM и вообще плохо. Ну а также, советую ознакомится с этим, чтоб понять почему <vm:ItemsVM></vm:ItemsVM> плохо. – EvgeniyZ Sep 24 '21 at 20:28
  • https://ru.stackoverflow.com/a/1266479/373567 – aepot Sep 24 '21 at 23:22
  • @aepot это не то что мне нужно – zelberman Sep 25 '21 at 08:08
  • Как вы это поняли? – aepot Sep 25 '21 at 08:19
  • @aepot У меня задача немного другая. В вашем примере просто навигация по приложению. Мне, как я уже писал нужно иначе сделать. Если есть предложения как поменять мою логику то пишите – zelberman Sep 25 '21 at 08:26
  • Я пока не понимаю, что именно вам нужно. Не в смысле войны с классами, которая подробно расписана, а в смысле, что же именно в окне должно происходить. Если сменить вьюху при клике на что-либо где-либо, то мое решение легко с этим справится. Но я не намерен вас уговаривать. – aepot Sep 25 '21 at 08:37
  • @aepot если взять мой xaml то будет в ListView элементы. Когда я на один из них нажимаю, то будет открываться новая вью. Но, как я писал выше то нужно еще получить инфу о том что это за элемент(на который мы нажали). Шаблон для странички одинаковый только текст будет разный. Аналогия закладки в браузере, мы нажимаем и открывается сайт – zelberman Sep 25 '21 at 08:55
  • Ну, не вижу ни одной причины, по которой вы решили, что решение не подходит. Ну ок, вам виднее. – aepot Sep 25 '21 at 09:02
  • @aepot Хорошо, как можно тогда обработать нажатие в одной VM и при переходе на другую VM передать информацию? – zelberman Sep 25 '21 at 09:17
  • 1
    VM либо уже содержит информацию, либо знает где ее взять. С точки зрения View, VM это и есть информация. Как сделать переключение View в зависимости от типа VM, я уже вам показал. А как обновлять данные без смены View - вы уже знаете - INotifyPropertyChanged. Привяжите часть View окна к свойству главной VM, создайте для нее шаблон. Команда будет только заниматься присваиванием свойства. Ну или вообще без команды, а так как показано в примере с привязкой SelectedItem. Это должно быть просто, вы запутались, распутывайтесь. – aepot Sep 25 '21 at 09:31
  • @aepot -"VM либо уже содержит информацию, либо знает где ее взять". У меня 2 VM, одна обрабатывает(ItemsVM) другая формирует(ElementVM) страницу на основе данных из ItemsVM. Как тогда последовательно вызвать обработчик нажатия в ItemVM и передать все в ElementVM, при этом создать новую страницу? – zelberman Sep 25 '21 at 11:59
  • @aepot или такая логика будет неправильной по отношение к MVVM? – zelberman Sep 27 '21 at 12:02
  • MVVM - это шаблон проектирования, он не отвечает за логику приложения. Он отвечает за разделение внутренней логики и представления, то есть интерфейса, а так же отделение от всего этого логики работы с данными. За счет этого обеспечивается модульность приложения, как следствие этого - приложение легче дорабатывать. Как именно логически ведут внутри себя эти разделенные части, MVVM не отвечает. – aepot Sep 27 '21 at 12:07
  • @aepot ну тогда как сделать что я выше написал, когда я запустил ваш код у меня появляется 2 окна и второе что мне мешает это то что 2 две мои VM не связаны интерфейсом, и скорее всего не должны у них только общий абстрактный класс – zelberman Oct 03 '21 at 08:59
  • 1
    Классика, откройте App.xaml и уберите SrartupUri оттуда, вы были недостаточно внимательны. – aepot Oct 03 '21 at 09:21
  • @aepot действительно не обратил внимание, но это ничего не меняет, я все так же откладываю решение и делаю что-то другое. Есть ли вообще способ реализовать это – zelberman Oct 04 '21 at 21:37
  • Дело ваше. Не планировал вас уговаривать. – aepot Oct 05 '21 at 00:28
  • @aepot Спустя месяц я отложил решение и до сих пор не могу решить эту проблему. Не могли бы написать пример реализации того что я описал выше – zelberman Nov 13 '21 at 13:27
  • Вам уже даны все примеры в ссылках выше. – aepot Nov 13 '21 at 13:43
  • @aepot а если они не подходят под данную модель логики. – zelberman Nov 13 '21 at 13:44
  • @aepot Я не понимаю как мне можно передавать информацию при переходе на новую страницу. Я же должен как-то фиксировать какой элемент я выбрал. И в соответствии формировать определенную информацию о нем. – zelberman Nov 13 '21 at 14:10
  • @aepot Повторю для понимания, что это как в интернет магазине. Когда нажимаете на товар, то открывается полная информация о нем. Тут у меня есть элементы, при нажатии на них у меня формируется страница с полной информации про них. – zelberman Nov 13 '21 at 14:15
  • Ну так тайл товара и страница товара могут формироваться из одной и той же вьюмодели. Одна вьюмодель, разные view. Вы просто меняете VM страницы с товарами на VM товара, по которому ткнули, и готово. Как сменить View в зависимости от выбранной VM, как раз и показано выше. С чего вы решили, что ссылки выше не несут никакой пользы - мне не понятно. Складывается впечатление только о том, что вы посмотрели, не захотели разбираться и закрыли предложенные решения. Как я выше написал, ваше право отказаться и разработать собственное, более понятное решение. Здесь я ничем помочь не могу. – aepot Nov 13 '21 at 15:35
  • @aepot С ссылками я ознакомился просто мне не понятно как добавить в них то что я хочу сделать. А именно как при нажатии я могу получить информацию о элементе(такой метод реализован) и при этом передать следующей Vm в формировании страницы. Если я буду менять vm то смысл тогда формировать все в одной(и разве не нарушает принцип SOLID) . Я видимо что-то плохо понимаю. – zelberman Nov 13 '21 at 15:58
  • Вам дали методику, а не решение. Есть разница. Решение вы берете и копируете себе в проект, а методику думаете как применить к своему собственному решению. SOLID здесь вообще не при чем. Вам решать, как будет устроена архитектура решения. Где нарушать и где не нарушать - тоже вам решать. – aepot Nov 13 '21 at 16:22
  • @aepot ну если я хочу для решения задачи использовать разные vm, то как мне сделать то что я выше описал. Передавать информацию и что бы все было последовательно – zelberman Nov 13 '21 at 16:50
  • Создать новую VM передав ей ссылку на Model с данными? Но для меня загадка, в чем смысл делать разные VM для одних и тех же данных. – aepot Nov 13 '21 at 17:01
  • @aepot если у меня разные VM то как их поместить в PageViewModels? – zelberman Nov 13 '21 at 17:10
  • Унаследовать общий интерфейс или базовый класс. ООП вас спасет. – aepot Nov 13 '21 at 17:14
  • @aepot в примере у вас отдельно навигация и интерфейс. У меня это все идет в ListView>Grid. И когда я нажимаю на элемент нужно открыть один и тот же шаблон просто с разной информацией в зависимости от нажатого элемента – zelberman Nov 29 '21 at 12:37

0 Answers0