0

Как передать в user control текущий экземпляр, чтобы его использовать для привязки внутри user control (ItemCard).

Строчка <customcontrols:ItemCard></customcontrols:ItemCard> Это и есть user control (ItemCard)

MainViewModel.cs

using Organaizer.MVVM.Model;
using Organaizer.MVVM.View;
using Organaizer.MVVM.ViewModel.Base;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;

namespace Organaizer.MVVM.ViewModel { public class MainViewModel : BaseViewModel {

    private ObservableCollection&lt;ItemInfoCard&gt; _itemInfoCards = new ObservableCollection&lt;ItemInfoCard&gt;() {
        new ItemInfoCard(E_CategoryGroup.dir, false),
        new ItemInfoCard(E_CategoryGroup.exe, false)
    };
    public IEnumerable&lt;ItemInfoCard&gt; ItemInfoCards
    {
        get =&gt; _categoryGroup==E_CategoryGroup.favorite? _itemInfoCards.Where(item =&gt; item.IsFavorite == true) : _itemInfoCards.Where(item =&gt; item.CategoryGroup == _categoryGroup);
    }
    public void Initialize()
    {
        _itemInfoCards.Add(new ItemInfoCard(E_CategoryGroup.exe, true));
    }

    #region Commands

    private ICommand _cmdSelectedGroup;
    public ICommand CmdSelectedGroup =&gt; _cmdSelectedGroup = new RelayCommand&lt;string&gt;(SelectedGroup);
    private void SelectedGroup(string value)
    {
        _categoryGroup = (E_CategoryGroup) Enum.Parse(typeof(E_CategoryGroup), value);
        RisePropertyChanged(nameof(ItemInfoCards));
    }


    private ICommand _cmdAddElement;
    public ICommand CmdAddElement =&gt; _cmdAddElement = new RelayCommand(AddElement);
    private void AddElement(object item)
    {
        SelectAddType vm = new SelectAddType(this);
        vm.Show();
    }


    private ICommand _cmdSelectFavorite;
    public ICommand CmdSelectFavorite =&gt; _cmdSelectFavorite = new RelayCommand&lt;bool&gt;(SelectFavorite);
    private void SelectFavorite(bool value)
    {
        MessageBox.Show(value.ToString());
    }
    #endregion
}

}


MainWindows.xaml

            ScrollViewer Grid.Column="1" >
                <ItemsControl Grid.Column="0" ItemsSource="{Binding ItemInfoCards}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel Margin="20" VerticalAlignment="Top" Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <customcontrols:ItemCard></customcontrols:ItemCard>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>

ItemCard.xaml.cs

namespace Organaizer.UserControls
{
    /// <summary>
    /// Логика взаимодействия для ItemCard.xaml
    /// </summary>
    public partial class ItemCard : UserControl
    {
        public ItemCard()
        {
            InitializeComponent();
        }
    }
}

ItemCard

  • DataContext же. Он наследуется, поэтому скорее всего там уже все передано как надо. А вообще есть DependencyProperty https://ru.stackoverflow.com/a/1441493/373567 https://ru.stackoverflow.com/a/1137895/373567 – aepot Oct 04 '22 at 18:47
  • Что делает ItemCard? Если это контрол по типу TextBox, то он не должен знать вообще чего-либо про данные, он должен иметь конкретный вид, иметь конкретные свойства (свои), а снаружи уже этим свойствам задаются значения (<...:ItemCard Title = "Заголовок" Name = "Вася" Age = "123" />). Если это а-ля страница, со своим видом, данными и прочим, то там идет свое разделение на слои (View и VM), которые связываются через DataContext. – EvgeniyZ Oct 04 '22 at 18:52
  • @EvgeniyZ ItemCard достаточно много всего делает. Приложил скриншот на что он похож. Код громоздкий там конечно. Если нужно приложу – Андрей Reyz Oct 04 '22 at 18:55
  • 1
    Если делает много - значит он выполняет не свою ответственность, разделите на мелкие контролы. А так, ну сделайте свойства зависимости и привяжите их. Например, я вижу на скрине выше кнопку запуска, кнопку редактирования, кнопку избранного и еще наверно парочка команд в троеточие, наверно может и картинка есть, а не просто черный фон) Вот у вас получается несколько DependencyProperty с типом ICommand для всех кликов, а использование просто <uc:ItemCard Start = "{Binding ItemStartCommand}" .... />, как бы стандартные контролы) – EvgeniyZ Oct 04 '22 at 19:05
  • То есть, вы не объект пытайтесь сунуть туда, на основе которого контрол все сделает, а наоборот, сделайте универсальный контрол, с конкретным дизайном, у которого есть конкретные свойства, он не должен знать ничего про данные. А данные уже привязываете к каждому свойству контрола свои. – EvgeniyZ Oct 04 '22 at 19:07
  • @EvgeniyZ Да вы правы что там не так много команд и можно забиндить через DependencyProperty. Просто хотелось узнать, можно как то компактно это сделать ? Тогда придется передавать новую VM ? – Андрей Reyz Oct 04 '22 at 19:09
  • 1
    Контролы, это View слой, а если вы делаете все по правилам MVVM, то View не должен знать ничего про другие слои, ему должно быть без разницы какой объект идет на вход. Вот возьмите любой стандартный контрол, он на вход принимает интерфейс? Может конкретный класс? Да вроде нет. Каждый контрол имеет у себя конкретные свойства, которые созданы для выполнения конкретных его задач, а вы уже, как пользователь этих контролов, задаете им конкретные значения. 3-5 DependencyProperty это не так много, чтоб думать о "компактности", подумайте лучше о практичности, может этот контрол пригодится вам где еще. – EvgeniyZ Oct 04 '22 at 19:16
  • 1
    Ну а если нужна компактность, то тогда сразу внутри контрола задавайте привязки к нужным свойствам и тупо задавайте ему DataContext на класс, который содержит эти все свойства, будет вам просто <control DataContext = "{Binding Item}"/>, компактно? Да вроде да. Но что с практичностью, переиспользованием, и так далее? Как понимаете, вы гвоздями все внутри контрола забиваете, что не всегда есть хорошо. Поэтому думайте как лучше поступить именно в вашем случае. – EvgeniyZ Oct 04 '22 at 19:17
  • @EvgeniyZ Подскажите а как команду забиндить с текущей viewModel ? Так не получается, пишет Свойство MainViewModel не найдено для объекта типа ItemInfoCard.

    <customcontrols:ItemCard IsFavorite="{Binding IsFavorite}" FavoriteCommand="{Binding MainViewModel/CmdSelectFavorite}"></customcontrols:ItemCard>

    – Андрей Reyz Oct 04 '22 at 22:32
  • я так полагаю что так FavoriteCommand="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.CmdSelectFavorite } – Андрей Reyz Oct 04 '22 at 22:39
  • В коллекции у каждого элемента свой DataContext, ну а если нужен контекст родителя, то да, через FindAncestor находится родитель, и у него берется уже свойство. – EvgeniyZ Oct 04 '22 at 23:07
  • @EvgeniyZ вот только не могу понять. У меня есть комманда IsFavorite. Как я могу поменять значение? – Андрей Reyz Oct 04 '22 at 23:59
  • @АндрейReyz А почему это команда, а не bool переменная? Если это всеж bool и не обновляется, то попробуйте задать мод привязки на TwoWay (можете прям у DependencyProperty). – EvgeniyZ Oct 05 '22 at 00:11
  • @EvgeniyZ Ну а свойство slectedItemInfoCard нужно будет создавать, можно как то сразу передать в ICommand выбранный обьект ? – Андрей Reyz Oct 05 '22 at 00:28
  • @АндрейReyz Для передачи чего-либо в команду существуют ее параметры (свойство CommandParameter). – EvgeniyZ Oct 05 '22 at 00:44

0 Answers0