Перейти к содержимому

Как связать view и viewmodel wpf

  • автор:

Как связать view и viewmodel wpf

Для работы с паттерном MVVM создадим новый проект. По умолчанию в проект добавляется стартовое окно MainWindow — это и будет представление. И теперь нам нужна модель и ViewModel.

Добавим в проект новый класс Phone, который и будет представлять модель приложения:

using System.ComponentModel; using System.Runtime.CompilerServices; namespace MVVM < public class Phone : INotifyPropertyChanged < private string title; private string company; private int price; public string Title < get < return title; >set < title = value; OnPropertyChanged("Title"); >> public string Company < get < return company; >set < company = value; OnPropertyChanged("Company"); >> public int Price < get < return price; >set < price = value; OnPropertyChanged("Price"); >> public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") < if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); >> >

Для уведомления системы об изменениях свойств модель Phone реализует интерфейс INotifyPropertyChanged. Хотя в рамках паттерна MVVM это необязательно. В других конструкциях и ситуациях все может быть определено иначе.

Также добавим в проект новый класс ApplicationViewModel, который будет представлять модель представления:

using System.ComponentModel; using System.Runtime.CompilerServices; using System.Collections.ObjectModel; namespace MVVM < public class ApplicationViewModel : INotifyPropertyChanged < private Phone selectedPhone; public ObservableCollectionPhones < get; set; >public Phone SelectedPhone < get < return selectedPhone; >set < selectedPhone = value; OnPropertyChanged("SelectedPhone"); >> public ApplicationViewModel() < Phones = new ObservableCollection< new Phone < Title="iPhone 7", Company="Apple", Price=56000 >, new Phone , new Phone , new Phone >; > public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") < if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); >> >

Это класс модели представления, через который будут связаны модель Phone и представление MainWindow.xaml. В этом классе определен список объектов Phone и свойство, которое указывает на выделенный элемент в этом списке.

В итоге веcь проект будет выглядеть следующим образом:

Применение Model View ViewModel в WPF

Далее изменим код нашего представления — файла MainWindow.xaml:

             " /> " /> " />      " /> " /> " />   

Здесь определен элемент ListBox, который привязан к свойству Phones объекта ApplicationViewModel, а также определен набор элементов, которые привязаны к свойствам объекта Phone, выделенного в ListBox.

И изменим файл кода MainWindow.xaml.cs :

using System.Windows; namespace MVVM < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); DataContext = new ApplicationViewModel(); >> >

Здесь достаточно установить контекст данных для данного окна в виде объекта ApplicationViewModel, который свяжет представление и модели Phone.

И если мы запустим приложение, то увидим список объектов. Мы можем выбрать один из них, и его данные появятся в полях справа:

Реализация паттерна MVVM в WPF

При этом не надо определять код загрузки объектов в ListBox, определять обработчики выбора объекта в списке или сохранения его данных. За нас все делает механизм привязки данных.

Определение модели

В данном случае мы сами определяем модель Phone. Однако не всегда мы имеем возможность реализовать в используемой модели интерфейс INotifyPropertyChanged. Также, возможно, мы захотим предусмотреть отдельное представление (отдельное окно) для манипуляций над одной моделью (добавление, изменение, удаление). Подобное представление может иметь в качестве ViewModel объект модели Phone. И в подобных случаях мы можем создать отдельную ViewModel для работы с одним объектом Phone, наподобие:

using System.ComponentModel; using System.Runtime.CompilerServices; namespace MVVM < public class PhoneViewModel : INotifyPropertyChanged < private Phone phone; public PhoneViewModel(Phone p) < phone = p; >public string Title < get < return phone.Title; >set < phone.Title = value; OnPropertyChanged("Title"); >> public string Company < get < return phone.Company; >set < phone.Company = value; OnPropertyChanged("Company"); >> public int Price < get < return phone.Price; >set < phone.Price = value; OnPropertyChanged("Price"); >> public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") < if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); >> >

Паттерн MVVM

Паттерн MVVM (Model-View-ViewModel) позволяет отделить логику приложения от визуальной части (представления). Данный паттерн является архитектурным, то есть он задает общую архитектуру приложения.

Данный паттерн был представлен Джоном Госсманом (John Gossman) в 2005 году как модификация шаблона Presentation Model и был первоначально нацелен на разработку приложений в WPF. И хотя сейчас данный паттерн вышел за пределы WPF и применяется в самых различных технологиях, в том числе при разработке под Android, iOS, тем не менее WPF является довольно показательной технологией, которая раскрывает возможности данного паттерна.

MVVM состоит из трех компонентов: модели (Model), модели представления (ViewModel) и представления (View).

Паттерн MVVM в WPF

Model

Модель описывает используемые в приложении данные. Модели могут содержать логику, непосредственно связанную этими данными, например, логику валидации свойств модели. В то же время модель не должна содержать никакой логики, связанной с отображением данных и взаимодействием с визуальными элементами управления.

Нередко модель реализует интерфейсы INotifyPropertyChanged или INotifyCollectionChanged, которые позволяют уведомлять систему об изменениях свойств модели. Благодаря этому облегчается привязка к представлению, хотя опять же прямое взаимодействие между моделью и представлением отсутствует.

View

View или представление определяет визуальный интерфейс, через который пользователь взаимодействует с приложением. Применительно к WPF представление — это код в xaml, который определяет интерфейс в виде кнопок, текстовых полей и прочих визуальных элементов.

Хотя окно (класс Window) в WPF может содержать как интерфейс в xaml, так и привязанный к нему код C#, однако в идеале код C# не должен содержать какой-то логики, кроме разве что конструктора, который вызывает метод InitializeComponent и выполняет начальную инициализацию окна. Вся же основная логика приложения выносится в компонент ViewModel.

Однако иногда в файле связанного кода все может находиться некоторая логика, которую трудно реализовать в рамках паттерна MVVM во ViewModel.

Представление не обрабатывает события за редким исключением, а выполняет действия в основном посредством команд.

ViewModel

ViewModel или модель представления связывает модель и представление через механизм привязки данных. Если в модели изменяются значения свойств, при реализации моделью интерфейса INotifyPropertyChanged автоматически идет изменение отображаемых данных в представлении, хотя напрямую модель и представление не связаны.

ViewModel также содержит логику по получению данных из модели, которые потом передаются в представление. И также VewModel определяет логику по обновлению данных в модели.

Поскольку элементы представления, то есть визуальные компоненты типа кнопок, не используют события, то представление взаимодействует с ViewModel посредством команд.

Например, пользователь хочет сохранить введенные в текстовое поле данные. Он нажимает на кнопку и тем самым отправляет команду во ViewModel. А ViewModel уже получает переданные данные и в соответствии с ними обновляет модель.

Итогом применения паттерна MVVM является функциональное разделение приложения на три компонента, которые проще разрабатывать и тестировать, а также в дальнейшем модифицировать и поддерживать.

C# WPF MVVM связь ViewModel — Model и ViewModel — ViewModel

У меня есть примерно такой View окна введите сюда описание изображения он состоит из 3 регионов: File Manager, Workspace и Menu. Мне нужно сделать добавление файла с помощью кнопки Menu в File Manager, View окна добавления очень простой введите сюда описание изображения TextBox Name должен проверять существует ли такой файл и Border должен ставать красным если существует. Я должен сделать это строго по MVVM введите сюда описание изображения и собственно говоря столкнулся с 2 вопросами: Как я понимаю Add File View Model должна говорить Add File View существует ли файл с таким именем, т.е должна быть модель которая будет получать коллекцию имен и им’я c Add File View и проверять сходство. Здесь нужно взять имена с File Manager Model и отправить в Add File Model, как это сделать? Можно создать свойство в File Manager View Model и через Binding как параметр скормить коллекцию имен команде которая открывает окно добавления нового файла но не нарушает ли такой подход MVVM? 2 Вопрос о связи между ViewModel и Model, насколько я знаю Model может иметь свойства которые имплементуруют INotifyPropertyChanged и View может к ним делать Binding, но как на меня это превращает Model в View Model, рассматривая Model со свойствами которые не имплементуруют INotifyPropertyChanged эти свойства нужно обернуть в View Model, как Model должна уведомлять об изменении View Model? о Prism, EventAggregator знаю, меня интересует решение без фреймворка

Отслеживать
задан 25 дек 2019 в 11:11
Mike Waters Mike Waters
330 5 5 серебряных знаков 24 24 бронзовых знака
Возможно, это немного по теме.
27 окт 2021 в 10:16

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Если вы писали по старинке без mvvm приложения то тогда поймете. VM это почти тоже самое как xaml.cs файл раньше в которым мы писали логику интерфейса и данных. Так же и здесь, в VM уходит логика интерфейса и некоторые данные если упрощать. Логику работы с данными тут уже нужно выносить. То есть как вы и думали можно сделать список List файлов прямо во VM и забиндить на него вашу stackpanel или какой вы там элемент используете. А Model это уже Класс ваших файлов и их свойства которые вы будете дальше использовать. Получается биндим к List .

Может термины где то я пишу не совсем правильные, но именно такую логику предоставляют гайды по mvvm. В частности тот что на хабре. То есть те элементы которые мы ходим менять во View пишем во ViewModel? а потом передаем дальше измененные данные в другие классы/методы для работы.

Отслеживать
ответ дан 25 дек 2019 в 11:32
193 12 12 бронзовых знаков

1) В ответе на 2 вопрос я вам написал, что ViewModel должна давать представлению коллекцию объектов (ObservableCollection), которые представляют собой файл. Для вашего функционала с добавлением файла достаточно всего 1 команды, которая проверяет, есть ли в коллекции такой элемент, если есть, то устанавливает у него созданное вами свойство (булевское), которое биндится на Visibility бордера и преобразовывается из bool в Visibility. А если нет, то добавляет новую модель в ObservableCollection и она автоматически появляется в списке. Также не забудьте про метод CanExecute. Тут все очень просто, если значение в поле пустое, то нельзя добавить файл. Что касательно открытие нового окна. То здесь подход очень простой. Только View может создавать View. Код создания нового View нужно писать во вью. Можете писать декларативно, можете в CodeBehind.

2) Модель может реализовывать INotifyPropertyChanged. Скажу больше, это абсолютно нормально. Как реальный жизненный пример я вам могу привести в пример любую сущность из БД. Она с точки зрения MVVM является моделью. Вы не совсем правильно понимаете, что такое Model и ViewModel. ViewModel переводится как модель представления, т.е. это ФУНКЦИОНАЛЬНЫЕ ВОЗМОЖНОСТИ графического ИНТЕРФЕЙСА пользователя и в ней пишется код который реализует поведение интерфейса пользователя, а Model это реализация бизнес-логики (она же функциональность приложения). В вашем случае ViewModel должна возвращать коллекцию моделей (файлов) (лучше всего ObservableCollection), у которых есть свойство со значением имени, и это коллекция биндится на какой-нибудь контрол (например, ListBox с переопределенным шаблоном элемента). И на вашей картинке, которую вы привели, под состоянием модели имеется намного больше, чем простое изменение свойств. Вы не забывается, что под этими тремя квадратиками имеется ввиду 3 крупшейние части приложения (там может быть под 2к файлов, где, например, 800 файлов это View, 800 это ViewModel, а оставшиеся 400 это модели) и под состоянием модели может иметься ввиду значения кучи объектов одновременно.

Отслеживать
ответ дан 27 дек 2019 в 14:33
79 2 2 бронзовых знака

  • c#
  • wpf
    Важное на Мете
Связанные
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Привязка данных и MVVM

Шаблон Model-View-ViewModel (MVVM) обеспечивает разделение между тремя слоями программного обеспечения — пользовательским интерфейсом XAML, который называется представлением, базовыми данными, называемыми моделью, и посредником между представлением и моделью, называемой моделью представления. Представление и модель представления часто подключаются через привязки данных, определенные в XAML. Представление BindingContext обычно является экземпляром модели представления.

Многоплатформенный пользовательский интерфейс приложения .NET (.NET MAUI) маршалирует обновления привязки к потоку пользовательского интерфейса. При использовании MVVM это позволяет обновлять свойства представления, привязанные к данным, из любого потока, с подсистемой привязки .NET MAUI, которая позволяет обновлять поток пользовательского интерфейса.

Существует несколько подходов к реализации шаблона MVVM, и в этой статье рассматривается простой подход. Он использует представления и модели представления, но не модели, чтобы сосредоточиться на привязке данных между двумя уровнями. Подробное описание использования шаблона MVVM в .NET MAUI см. в статье Model-View-ViewModel (MVVM) в шаблонах корпоративных приложений с помощью .NET MAUI. Руководство по реализации шаблона MVVM см. в разделе «Обновление приложения с помощью концепций MVVM».

Простой MVVM

В расширениях разметки XAML вы узнали , как определить новое объявление пространства имен XML, чтобы позволить XAML-файлу ссылаться на классы в других сборках. В следующем примере используется x:Static расширение разметки для получения текущей даты и времени из статического DateTime.Now свойства в System пространстве имен:

  '>" /> '>" /> '>" /> '>" />  

В этом примере извлекаемое DateTime значение задается как значение в объекте StackLayout BindingContext . При установке BindingContext элемента он наследуется всеми дочерними элементами этого элемента. Это означает, что все дочерние элементы StackLayout одного и того же BindingContext , и они могут содержать привязки к свойствам этого объекта:

Screenshot of a page displaying the date and time.

Однако проблема заключается в том, что дата и время задаются один раз при создании и инициализации страницы и никогда не изменяются.

Страница XAML может отображать часы, которые всегда показывают текущее время, но требует дополнительного кода. Шаблон MVVM является естественным выбором для приложений .NET MAUI при привязке данных из свойств между визуальными объектами и базовыми данными. При мышлении с точки зрения MVVM модель и модель представления являются классами, написанными полностью в коде. Представление часто представляет собой XAML-файл, который ссылается на свойства, определенные в представлении с помощью привязок данных. В MVVM модель не учитывается в режиме просмотра, и модель представления не учитывается. Однако часто вы настраиваете типы, предоставляемые в режиме просмотра, с типами, связанными с пользовательским интерфейсом.

В простых примерах MVVM, таких как показанные здесь, часто нет модели вообще, и шаблон включает только представление и представление, связанное с привязками данных.

В следующем примере показана модель представления для часов с одним свойством, которое DateTime обновляется каждую секунду:

using System.ComponentModel; using System.Runtime.CompilerServices; namespace XamlSamples; class ClockViewModel: INotifyPropertyChanged < public event PropertyChangedEventHandler PropertyChanged; private DateTime _dateTime; private Timer _timer; public DateTime DateTime < get =>_dateTime; set < if (_dateTime != value) < _dateTime = value; OnPropertyChanged(); // reports this property >> > public ClockViewModel() < this.DateTime = DateTime.Now; // Update the DateTime property every second. _timer = new Timer(new TimerCallback((s) =>this.DateTime = DateTime.Now), null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); > ~ClockViewModel() => _timer.Dispose(); public void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); > 

Viewmodels обычно реализует INotifyPropertyChanged интерфейс, который предоставляет возможность для класса вызывать PropertyChanged событие всякий раз, когда одно из его свойств изменяется. Механизм привязки данных в .NET MAUI присоединяет обработчик к этому PropertyChanged событию, чтобы его можно было получать уведомления при изменении свойства и обновлять целевой объект новым значением. В предыдущем примере OnPropertyChanged кода метод обрабатывает событие при автоматическом определении имени источника свойства: DateTime

В следующем примере показано XAML, которое использует ClockViewModel :

    '>" FontSize="18" HorizontalOptions="Center" VerticalOptions="Center" /> 

В этом примере ClockViewModel задано значение BindingContext тегов ContentPage элементов свойства. Кроме того, файл программной части может создать экземпляр viewmodel.

Binding Расширение разметки Label для Text свойства форматирования DateTime свойства. На следующем снимка экрана показан результат:

Screenshot of a page displaying the date and time via a viewmodel.

Кроме того, можно получить доступ к отдельным свойствам DateTime свойства объекта viewmodel, разделив свойства с точками:

Интерактивный MVVM

MVVM часто используется с двусторонними привязками данных для интерактивного представления на основе базовой модели данных.

В следующем примере показано HslViewModel , как преобразовать Color значение в Hue , Saturation а также Luminosity значения и вернуться обратно:

using System.ComponentModel; using System.Runtime.CompilerServices; namespace XamlSamples; class HslViewModel: INotifyPropertyChanged < public event PropertyChangedEventHandler PropertyChanged; private float _hue, _saturation, _luminosity; private Color _color; public float Hue < get =>_hue; set < if (_hue != value) Color = Color.FromHsla(value, _saturation, _luminosity); >> public float Saturation < get =>_saturation; set < if (_saturation != value) Color = Color.FromHsla(_hue, value, _luminosity); >> public float Luminosity < get =>_luminosity; set < if (_luminosity != value) Color = Color.FromHsla(_hue, _saturation, value); >> public Color Color < get =>_color; set < if (_color != value) < _color = value; _hue = _color.GetHue(); _saturation = _color.GetSaturation(); _luminosity = _color.GetLuminosity(); OnPropertyChanged("Hue"); OnPropertyChanged("Saturation"); OnPropertyChanged("Luminosity"); OnPropertyChanged(); // reports this property >> > public void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); > 

В этом примере изменения свойств Hue Saturation и Luminosity свойств приводят Color к изменению свойства, а изменение Color свойства приводит к изменению других трех свойств. Это может показаться бесконечным циклом, за исключением того, что viewmodel не вызывает PropertyChanged событие, если свойство не изменилось.

Следующий пример XAML содержит свойство, свойство которого привязано BoxView к Color свойству viewmodel, а три и три SliderLabel представления привязаны к Hue свойствам , Saturation а Luminosity Color также свойствам:

    " HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" /> '>" HorizontalOptions="Center" /> " Margin="20,0,20,0" /> '>" HorizontalOptions="Center" /> " Margin="20,0,20,0" /> '>" HorizontalOptions="Center" /> " Margin="20,0,20,0" />  

Привязка для каждой из них Label — это значение по умолчанию OneWay . Оно должно отображаться только для отображения значения. Однако привязка по умолчанию для каждой из них Slider имеет значение TwoWay . Это позволяет Slider инициализироваться из модели представления. При создании экземпляра Color объекта viewmodel для свойства задано значение Aqua . Изменение в Slider наборе нового значения для свойства в режиме просмотра, которое затем вычисляет новый цвет:

MVVM using two-way data bindings.

Система команд

Иногда приложению требуется выйти за рамки привязок свойств, требуя от пользователя инициировать команды, влияющие на что-то в режиме просмотра. Эти команды обычно обозначаются путем нажатия кнопки или касания пальцем и традиционно обрабатываются в файле с выделенным кодом в обработчике для события Clicked объекта Button или события Tapped объекта TapGestureRecognizer.

Командный интерфейс предоставляет альтернативный подход к реализации команд, который гораздо лучше подходит для архитектуры MVVM. Модель представления может содержать команды, которые являются методами, выполняемыми в реакции на определенное действие в представлении, например щелчком Button мыши. Привязки данных определяются между этими командами и объектом Button.

Чтобы разрешить привязку данных между a Button и viewmodel, Button определяет два свойства:

  • Command типа System.Windows.Input.ICommand
  • CommandParameter типа Object

Многие другие элементы управления также определяют Command и CommandParameter свойства.

Интерфейс ICommand определяется в пространстве имен System.Windows.Input и состоит из двух методов и одного события:

  • void Execute(object arg)
  • bool CanExecute(object arg)
  • event EventHandler CanExecuteChanged

Модель представления может определять свойства типа ICommand. Затем эти свойства можно привязать к Command свойству каждого Button или другого элемента или, возможно, пользовательское представление, реализующее этот интерфейс. При необходимости можно задать CommandParameter свойство для идентификации отдельных Button объектов (или других элементов), привязанных к этому свойству viewmodel. Внутри этого метода вызывается всякий раз, Button когда пользователь нажимает методButton, передав его методу Execute CommandParameter . Execute

Метод CanExecute и CanExecuteChanged событие используются для случаев, когда Button касание в настоящее время может быть недопустимым, в этом случае Button следует отключить сам. Вызовы CanExecute Button при Command первом наборе свойства и при CanExecuteChanged возникновении события. Если CanExecute возвращается false , Button он отключает и не создает Execute вызовы.

Для реализации интерфейса можно использовать класс или Command класс, включенный Command ICommand в .NET MAUI. Эти два класса определяют несколько конструкторов, а также ChangeCanExecute метод, который может вызвать метод viewmodel, чтобы Command принудительно вызвать объект для вызова CanExecuteChanged события.

В следующем примере показана модель представления для простой клавиатуры, предназначенной для ввода телефонных номеров:

using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; namespace XamlSamples; class KeypadViewModel: INotifyPropertyChanged < public event PropertyChangedEventHandler PropertyChanged; private string _inputString = ""; private string _displayText = ""; private char[] _specialChars = < '*', '#' >; public ICommand AddCharCommand < get; private set; >public ICommand DeleteCharCommand < get; private set; >public string InputString < get =>_inputString; private set < if (_inputString != value) < _inputString = value; OnPropertyChanged(); DisplayText = FormatText(_inputString); // Perhaps the delete button must be enabled/disabled. ((Command)DeleteCharCommand).ChangeCanExecute(); >> > public string DisplayText < get =>_displayText; private set < if (_displayText != value) < _displayText = value; OnPropertyChanged(); >> > public KeypadViewModel() < // Command to add the key to the input string AddCharCommand = new Command((key) => InputString += key); // Command to delete a character from the input string when allowed DeleteCharCommand = new Command( // Command will strip a character from the input string () => InputString = InputString.Substring(0, InputString.Length - 1), // CanExecute is processed here to return true when there's something to delete () => InputString.Length > 0 ); > string FormatText(string str) < bool hasNonNumbers = str.IndexOfAny(_specialChars) != -1; string formatted = str; // Format the string based on the type of data and the length if (hasNonNumbers || str.Length < 4 || str.Length >10) < // Special characters exist, or the string is too small or large for special formatting // Do nothing >else if (str.Length < 8) formatted = string.Format("-", str.Substring(0, 3), str.Substring(3)); else formatted = string.Format("() -", str.Substring(0, 3), str.Substring(3, 3), str.Substring(6)); return formatted; > public void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); > 

В этом примере Execute команды определяются CanExecute как лямбда-функции в конструкторе. В представлении предполагается, что AddCharCommand свойство привязано к Command свойству нескольких кнопок (или других элементов управления, имеющих командный интерфейс), каждое из которых определяется элементом CommandParameter управления. Эти кнопки добавляют символы в InputString свойство, которое затем форматируется как номер телефона для DisplayText свойства. Существует также второе свойство типа ICommand с именем DeleteCharCommand . Это привязано к кнопке с интервалом назад, но кнопка должна быть отключена, если нет символов для удаления.

В следующем примере показан КОД XAML, который использует KeypadViewModel следующий код:

               " Margin="0,0,10,0" FontSize="20" LineBreakMode="HeadTruncation" VerticalTextAlignment="Center" HorizontalTextAlignment="End" Grid.ColumnSpan="2" /> " Grid.Column="2"/> " CommandParameter="1" Grid.Row="1" /> " CommandParameter="2" Grid.Row="1" Grid.Column="1" /> " CommandParameter="3" Grid.Row="1" Grid.Column="2" /> " CommandParameter="4" Grid.Row="2" /> " CommandParameter="5" Grid.Row="2" Grid.Column="1" /> " CommandParameter="6" Grid.Row="2" Grid.Column="2" /> " CommandParameter="7" Grid.Row="3" /> " CommandParameter="8" Grid.Row="3" Grid.Column="1" /> " CommandParameter="9" Grid.Row="3" Grid.Column="2" /> " CommandParameter="*" Grid.Row="4" /> " CommandParameter="0" Grid.Row="4" Grid.Column="1" /> " CommandParameter="#" Grid.Row="4" Grid.Column="2" />  

В этом примере Command свойство первого Button , привязанного к объекту DeleteCharCommand . Другие кнопки привязаны к AddCharCommand объекту, который совпадает с CommandParameter символом, отображаемым на Button:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *