WPF MVVM Multibinding - Как передать два параметра в команду с помощью RelayCommand

Как передать 2 параметра команде с помощью RelayCommand. Мне нужно передать COntrols в качестве параметров (сетка и окно). Я полностью осознаю, что такая проблема уже существовала в Stack Overflow, но я изо всех сил пытаюсь приспособить ее к своим потребностям.

  1. Смотрите, смотрите, моя первая попытка следующая. Очевидно, это не работает, потому что Relay не может получить 2 аргумента.

Код Xaml:

        <Button Name = "StretchScreenBtn" Content = "Stretch screen" DataContext = "   {StaticResource CommandWindow}" Command = "{Binding ResizeScreenCommand}"
                Width = "100" Height = "50">
             <Button.CommandParameter>
                <MultiBinding Converter = "{StaticResource CommandParamsConv}">
                    <Binding ElementName = "ScreenGrid" />
                    <Binding RelativeSource = "{RelativeSource AncestorType=Window}" /> 
                </MultiBinding> 
            </Button.CommandParameter>  
        </Button>

Код команды из ViewModel:

        private ICommand _ResizeScreenCommand;
        public ICommand ResizeScreenCommand
        {
            get
            {
                if (_ResizeScreenCommand == null)
                {
                    _ResizeScreenCommand = new RelayCommand(
                        (argument1, argument2) =>
                        {

                            Grid grid = argument1 as Grid;
                            Window window = argument2 as Window;
                            if ((int)grid.GetValue(Grid.ColumnSpanProperty) == 2)
                            {
                                grid.SetValue(Grid.ColumnSpanProperty, 1);
                                window.WindowStyle = WindowStyle.None;
                            }
                            else
                            {
                                grid.SetValue(Grid.ColumnSpanProperty, 2);
                                window.WindowStyle = WindowStyle.SingleBorderWindow;
                            }
                        }
                        );
                }
                return _ResizeScreenCommand;
            }
        }

И MultiValueConverter:

     class CommandParamsConverter : IMultiValueConverter
     {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            object[] parameters = values;
            return parameters;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
     }
  1. Моя вторая попытка Я последовал решению от Как передать несколько параметров RelayCommand?

Итак, я создал в ViewModel новый класс с двумя свойствами Grid и Window, а затем попытался привязать элементы к этим свойствам в xaml. Но в этом случае компилятор жалуется, что эти свойства не зависят и не могут быть привязаны.

Подскажите, пожалуйста, как это решить?

Ниже приведен измененный код xaml:

        <Button Name = "StretchScreenBtn" Content = "Stretch screen" DataContext = "{StaticResource CommandWindow}" Command = "{Binding ResizeScreenCommand}"
                Width = "100" Height = "50">
             <Button.CommandParameter>
                <vm:StretchingModel Grid = "{Binding ElementName=ScreenGrid}" Win = "{Binding RelativeSource = {RelativeSource AncestorType=Window}}" />
            </Button.CommandParameter>  
        </Button>

И дополнительный класс в ViewModel:

    class StretchingModel
    {
        public Grid Grid { get; set; }
        public Window Win { get; set; }
    } 

Итак, вы хотите привязать элементы управления к команде (что не одобряется и настоятельно не рекомендуется), и вы уже знаете ответ на заголовок своего вопроса. Я просто скажу использовать MVVM и не привязывать элементы управления ни к чему.

Bizhan 17.07.2018 19:31

Да, я знаю, но я не использую элементы управления по их именам в коде программной части. Я имею в виду, что они передаются из представления в модель представления, а модель VieModel видит их как тип объекта, а затем преобразует их в соответствующие типы (сетка и окно). В любом случае, Биджан, не могли бы вы предложить свою идею, как бы вы сделали эту привязку?

M_K 17.07.2018 19:57

идея - стандартный MVVM, где ВМ не знает о View. независимо от того, какой View вам нужно использовать для привязки, наверняка есть виртуальная машина, которую следует использовать. А для визуализации виртуальной машины, какой бы стиль или шаблон ни использовался для визуализации представления, в первую очередь можно использовать для визуализации привязанной виртуальной машины.

Bizhan 17.07.2018 20:09

Хорошо, я попробую это сделать. Но что в случае диалоговых окон в MVVM? Мне нужно было бы использовать OpenFileDialog, чтобы я создал соответствующие классы в представлении, а затем использовал созданный класс OpenFileDialog из представления в XAML, чтобы установить значения свойств (например, Caption, Filter и т. д.) И привязать его к любой кнопке Command, которая будет запустить окно. И тогда мне также нужно было бы передать FilePath из представления в команду в ViewModel, которая будет обрабатывать открытие файла и как это сделать? Вы когда-нибудь работали с диалоговыми окнами в Xaml. Не могли бы вы мне намекнуть?

M_K 17.07.2018 20:36

этот пост может помочь с OpenFileDialogstackoverflow.com/q/1619505/366064

Bizhan 17.07.2018 20:40

Хорошо, спасибо, я тоже попробую. Если я не смогу решить эту проблему, я активирую проблему повторно.

M_K 17.07.2018 20:49

Передача элемента управления и окна в модель просмотра - это не mvvm, поэтому ваше решение - просто делать то, что вы собираетесь делать в коде. Пахнет так, как будто вы переместили логику пользовательского интерфейса в модель представления. Это не MVVM. Логика представления принадлежит представлению внутри кода.

user1228 17.07.2018 20:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
877
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Передача Grid и Window в модель представления - это не MVVM ... модель представления не должна иметь никаких зависимостей от каких-либо элементов пользовательского интерфейса.

В любом случае, чтобы передать команде более одного значения, вы должны объединить два подхода. Конвертер должен вернуть экземпляр StretchingModel:

class CommandParamsConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new StretchingModel() { Grid = values[0], Window = values[1] };
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

... что команда принимает:

private ICommand _ResizeScreenCommand;
public ICommand ResizeScreenCommand
{
    get
    {
        if (_ResizeScreenCommand == null)
        {
            _ResizeScreenCommand = new RelayCommand(
                (argument) =>
                {

                    StretchingModel model = argument as StretchingModel;
                    ...
                }
                );
        }
        return _ResizeScreenCommand;
    }
}

Другие вопросы по теме