Страницы

Поиск по вопросам

Показаны сообщения с ярлыком mvvm-light. Показать все сообщения
Показаны сообщения с ярлыком mvvm-light. Показать все сообщения

пятница, 24 января 2020 г.

WPF MVVM - Анимация перехода между представлениями

#wpf #анимация #mvvm #mvvm_light


Разрабатываю проект на WPF с использованием паттерна MVVM. Использую MVVM Light.
Каким образом возможно реализовать анимацию переходов от одного представления к другому?
К примеру, плавное "затухание" одного и появление другого.
    


Ответы

Ответ 1



Не знаю как это делается в MVVM Light, я обычно определяю StoryBoard внутри нужного элемента c нужной анимацией, привязываю триггер анимации к нужному свойству элемента, через который реализован переход (скажем, Button.IsPressed). Все работает. Здесь поподробнее https://msdn.microsoft.com/ru-ru/library/ms742868(v=vs.110).aspx

Принцип, структура и использование WPF фреймворка mvvmlight

#c_sharp #wpf #mvvm #mvvm_light


Пытаюсь разобраться с MVVM Light. И чем дальше, тем страшнее. Вопросы возникают как
снежный ком. В сети не нашел ни одной статьи, где бы простым русским языком объяснялся
бы mvvm-light и его практическое применение. Ниже я приведу места и моменты, которые
вызывают у меня непонимание.

Установил на VisualStudio 2015 MVVM Light, создал новый проект MvvmLight(WPF451).
В проекте создались следующие файлы и папки:

[Design]
    DesignDataService.cs
[Model]
    DataItem.cs
    DataService.cs
    IDataService.cs
[Skins]
    MainSkin.xaml
[ViewModel]
    MainViewModel.cs
    ViewModelLocator.cs
App.xaml
App.xaml.cs
MainWindow.xaml
MainWindow.xaml.cs


В файле App.xaml видим следующее .
Как было выяснено здесь, это не подходит по ряду причин, а поэтому нужно удалить этот
атрибут и в перегруженном методе OnStartup класса App создать экземпляр необходимой
модели представления и установить её как DataContext, примерно так:

public partial class App : Application {

    MainViewModel mainVM = new MainViewModel();

    static App() {
        DispatcherHelper.Initialize();
    }

    protected override void OnStartup(StartupEventArgs e) {
        base.OnStartup(e);
        new MainWindow() { DataContext = mainVM }.Show();
    }
}


, но при использовании в созданном проекте mvvm-light класс MainViewModel принимает
в конструкторе IDataService dataService. В проекте так и не нашел каким образом создается
этот dataService. Для каждой ли модели представления нужно этот dataService создавать?
Как, когда и где он используется?

Также в созданном проекте присутствует класс ViewModelLocator. В комментарии класса
указан пример использования:

/*
In App.xaml:

    


In the View:
DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
*/


, но вроде же как явное указание DataContext в XAML неправильно?! Или я не прав?!
Для чего и как он используется?  

В code-behind представления MainWindow к событию Closing добавляется очистка ViewModelLocator:


Closing += (s, e) => ViewModelLocator.Cleanup();


, но в ViewModelLocator ничего не добавляется. Или это происходит где-то далеко за
кулисами?!

В файле MainWindow.xaml существует привязка к ресурсу:


    
        
            
        
    



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



В сети присутствует множество примеров mvvm-light, но они все сводятся к слепому
следованию инструкциям, без пояснения для чего это делается и как это в последствии
используется. Предвидя упреки об изучении мат.части, отмечу, что мне лично материал
легче усваивается на практике. И не хотелось бы колотить себе шишки, а перенять опыт
знающих людей и сразу учить как нужно делать, а не как можно. Может существует какой-либо
проект в сети, который подробно описывает использование mvvm-light фреймворка на русском?
    


Ответы

Ответ 1



Самое простое - следовать рекомендации, и делать все через ViewModelLocator. DataService создается через инъекции из IoС контейнера. Так регистрация происходит в ViewModelLocator.cs в конструкторе пишем SimpleIoc.Default.Register(); где DebugDataContext - конкретная реализация интерфейса IDataTask например база данных для дебага, а в продакшене будет с другого места браться (но это уже совсем другая история). Регистрируем VM SimpleIoc.Default.Register(); Выставляем ее на публику public MainViewModel Main => ServiceLocator.Current.GetInstance(); Все это есть уже по умолчанию, для других форм просто по аналогии. И вот когда вьюха будет обращаться к VM посредством того кода в XAML автоматически через IoC будет цепляться нужный источник данных. Вам там ответили, что вьюха не должна создавать VM. но она и не создает, создает IoC-контейнер, вьюха только запрашивает его экземпляр. Так что вам там не совсем верно ответили, без инъекций все действительно так, но в MVVM Light уже есть IoC и вся парадигма строится вокруг инъекций В коде можно тоже, если очень хочется, но лично я не вижу в этом смысла mainVM = ServiceLocator.Current.GetInstance(); Конечно всё это ИМХО, у VlaD'a свои взгляды, у меня свои, и MVVM это не святое писание, а просто идея и используют ее по разному, но по задумке создателей MVVM Light это должно делаться примерно так как я описал.

пятница, 20 декабря 2019 г.

Постраничная навигация при помощи MVVM Light

#c_sharp #wpf #mvvm_light


скажите, как лучше организовать постраничную навигацию, если используется mvvm light?
предполагается главное окно, страница по умолчанию и еще несколько, все в главном окне
    


Ответы

Ответ 1



Объявляем интерфейс: public interface INavigationService { void Navigate(Type type); void Navigate(Type type, object parameter); void EnsureNavigated(Type pageType, object parameter); bool CanGoBack { get; } bool CanGoForward { get; } void GoBack(); void GoForward(); IView CurrentView { get; } } Реализуем этот интерфейc: using System; using System.Collections.Generic; using System.Threading.Tasks; using Windows.UI.Xaml.Controls; public class NavigationService : INavigationService { private readonly Frame _frame; public NavigationService(Frame frame) { _frame = frame; _frame.Navigated += OnFrameNavigated; } private void OnFrameNavigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e) { var view = e.Content as IView; if (view == null) return; var navMsg = new NavigationMessage() { Sender = this, NewView = view, Parameter = e.Parameter, NavigationMode = (int)e.NavigationMode }; EventManager.Current.Publish(navMsg); var viewModel = view.ViewModel; if (viewModel != null) viewModel.Initialise(e.Parameter); } public void Navigate(Type pageType) { DisposePreviousView(); _frame.Navigate(pageType); } public void Navigate(Type pageType, object parameter) { DisposePreviousView(); _frame.Navigate(pageType, parameter); } private void DisposePreviousView() { var currentView = this.CurrentView; var currentViewDisposable = currentView as IDisposable; if (currentViewDisposable != null) { currentViewDisposable.Dispose(); currentViewDisposable = null; } } public void EnsureNavigated(Type pageType, object parameter) { var currentView = this.CurrentView; if (currentView == null || currentView.GetType() != pageType) { Navigate(pageType, parameter); } } public IView CurrentView { get { return _frame.Content as IView; } } public bool CanGoBack { get { return _frame != null && _frame.CanGoBack; } } public void GoBack() { if (_frame != null && _frame.CanGoBack) _frame.GoBack(); } public bool CanGoForward { get { return _frame != null && _frame.CanGoForward; } } public void GoForward() { if (_frame != null && _frame.CanGoForward) _frame.GoForward(); } } IView: public interface IView : IDisposable { IViewModel ViewModel { get; } void Refresh(); } IViewModel: public interface IViewModel : INotifyPropertyChanged, IDisposable { void Initialise(object parameter); string ViewTitle { get; } void Refresh(); } В ХАМЛе добавить фрейм элемент: В заднике: var _navigationService = new NavigationService(this.ContentFrame); Т.е. например так: public HomePage() { this.InitializeComponent(); var _navigationService = new NavigationService(this.ContentFrame); DataContext = new HomePageViewModel(_navigationService); } Еще рекомендую почитать эту статью.

Ответ 2



нашёл такое решение: xaml xmlns:viewModels="clr-namespace:iim.ViewModels" xmlns:views="clr-namespace:iim.Views" MainViewModel.cs using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; public class MainViewModel : ViewModelBase { private object selectedViewModel; public object SelectedViewModel { get { return selectedViewModel; } set { selectedViewModel = value; RaisePropertyChanged(() => SelectedViewModel); } } private ICommand _showGridView; public ICommand ShowGridView { get { return _showGridView ?? (_showGridView = new RelayCommand(() => { SelectedViewModel = new GridVieww(); })); } } }

понедельник, 9 декабря 2019 г.

Обязательны ли Фреймворки в C# для проектирования?

#c_sharp #mvvm #framework #mvvm_light


Можно создавать MVVM программы на C# без использования таких фреймворков например
как MVVM Light Toolkit? И очень ли сложно будет без них обойтись?
    


Ответы

Ответ 1



MVVM - это только паттерн проектирования, а значит если вы понимаете паттерн, то есть у вас готовый фреймворк или нет не имеет значения. В основном, необходимость использовать фреймворки и библиотеки исходит из масштаба проекта, решаемых задач, существующей кодовой базы и предпочтений тимлидов. Если проект большой и не использовались сторонние разработки, то большая часть вашей кодовой базы и будет тем самым фреймворком. А теперь более важные вопросы: Насколько большой проект? Сколько человек над ним работает? Насколько хорошо документирован ваш код? Сколько времени понадобится новому разработчику чтобы изучить и начать эффективно его использовать? В случае распространенных фреймворков эти вопросы стоят не так остро, т.к. в каком-то виде документация обычно есть, иногда есть техподдержка производителя, в сети достаточно решений типичных проблем на тематических форумах, EnSO и тут. Для небольшого проекта острой необходимости в тяжелых фреймворках нет, более того, за счет отсутствия тяжелых и неповоротливых "монстров" небольшой проект даже выиграет, если не надумает расти конечно. В случае большого проекта все не так однозначно. И да, это касается не только упомянутого вами MVVM, но и всех остальных областей, будь то WEB, работа с базами данных и т.д.

Ответ 2



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

пятница, 29 ноября 2019 г.

Точка входа в MVVM: App.xaml.cs или представление?

#c_sharp #wpf #mvvm #mvvm_light


Начал изучать MVVM и столкнулся, как наверное и многие другие, с определенным недопониманием.
В многочисленных примерах реализации MVVM, доступных в сети, авторы разными способами
подходят к точке входа в приложение (могу ошибаться в определении). Некоторые меняют
аттрибут StartupUri, другие просто его полностью удаляют и в перегруженном методе OnStartup
файла App.xaml.cs вручную создают экземпляр окна и устанавливают ему свойство DataContext.
Нашел в сети несколько примеров по MVVM и mvvm-light (пример 1, пример 1, пример 3,
пример 4 и пример 5) и в них автор вообще не изменяет App.xaml или App.xaml.cs и только
в одном изменяет code-behind (так и не понял как это называется по-русски) представлений.

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


Ответы

Ответ 1



Я предпочитаю не использовать StartupUri, а переопределять OnStartup, и создавать главное окно там ([1], [2], [3]). Причина в том, что указание StartupUri не позволяет задать DataContext снаружи окна. А хардкодирование DataContext'а внутри XAML неправильно, так как: Согласно паттерну MVVM, View не должно руководить VM, и знать о нём должно как можно меньше. То есть код, обслуживающий UI, не должен создавать себе VM сам. Чаще всего VM должна получить ещё какие-то аргументы в конструкторе (например, модельные объекты), а это не получится сделать, если VM создаётся в XAML'е (откуда XAML может знать о модели?). Иногда перед открытием главного окна нужна дополнительная логика, требующая показа своего маленького окна (например, предложение обновить программу). Или нужно выяснить, какое именно из окон нужно показывать в начале. Код, выясняющий это и при некоторых условиях показывающий дополнительное окно, проще разместить в OnStartup. Главная VM может понадобиться вам для ещё чего-нибудь. Поэтому если её создаёт класс App, он может сохранить ссылку на неё у себя, чтобы другие (например, побочное окно) могли быть привязаны к тому же экземпляру VM. Иначе вам придётся лезть за главной VM в экземпляр главного окна. В любом случае, MVVM не догма, делайте так, как вам удобнее.

четверг, 11 июля 2019 г.

c# wpf mvvm light как передать object sender в событии

есть devexpress grid control, в одной колонке которого comboBox. слушаю события SelectionChanged с помощью interaction и eventToCommand, но не знаю как получить сам comboBox (object sender), для определения строки, в которой данный comboBox, для получения их неё элемента, который биндится к этой строке. суть в том, что нужно отследить изменения в конкретной строке (получить guid, и новое значение, обновленное через comboBox). как получить object sender?


Ответ

xaml:

viewModel:
public RelayCommand ComboChanged { get; set; } public ViewModel() //ctor { ComboChanged = new RelayCommand(HandleComboChanged); } private void HandleComboChanged (SelectionChangedEventArgs a) { //(Combobox)a.Source }

вторник, 19 марта 2019 г.

WPF MVVM - Анимация перехода между представлениями

Разрабатываю проект на WPF с использованием паттерна MVVM. Использую MVVM Light. Каким образом возможно реализовать анимацию переходов от одного представления к другому? К примеру, плавное "затухание" одного и появление другого.


Ответ

Не знаю как это делается в MVVM Light, я обычно определяю StoryBoard внутри нужного элемента c нужной анимацией, привязываю триггер анимации к нужному свойству элемента, через который реализован переход (скажем, Button.IsPressed). Все работает. Здесь поподробнее https://msdn.microsoft.com/ru-ru/library/ms742868(v=vs.110).aspx

пятница, 9 ноября 2018 г.

Постраничная навигация при помощи MVVM Light

скажите, как лучше организовать постраничную навигацию, если используется mvvm light? предполагается главное окно, страница по умолчанию и еще несколько, все в главном окне


Ответ

нашёл такое решение:
xaml
xmlns:viewModels="clr-namespace:iim.ViewModels" xmlns:views="clr-namespace:iim.Views"


MainViewModel.cs
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command;
public class MainViewModel : ViewModelBase { private object selectedViewModel; public object SelectedViewModel { get { return selectedViewModel; } set { selectedViewModel = value; RaisePropertyChanged(() => SelectedViewModel); } }
private ICommand _showGridView; public ICommand ShowGridView { get { return _showGridView ?? (_showGridView = new RelayCommand(() => { SelectedViewModel = new GridVieww(); })); } } }

суббота, 13 октября 2018 г.

Обязательны ли Фреймворки в C# для проектирования?

Можно создавать MVVM программы на C# без использования таких фреймворков например как MVVM Light Toolkit? И очень ли сложно будет без них обойтись?


Ответ

MVVM - это только паттерн проектирования, а значит если вы понимаете паттерн, то есть у вас готовый фреймворк или нет не имеет значения.
В основном, необходимость использовать фреймворки и библиотеки исходит из масштаба проекта, решаемых задач, существующей кодовой базы и предпочтений тимлидов. Если проект большой и не использовались сторонние разработки, то большая часть вашей кодовой базы и будет тем самым фреймворком.
А теперь более важные вопросы: Насколько большой проект? Сколько человек над ним работает? Насколько хорошо документирован ваш код? Сколько времени понадобится новому разработчику чтобы изучить и начать эффективно его использовать? В случае распространенных фреймворков эти вопросы стоят не так остро, т.к. в каком-то виде документация обычно есть, иногда есть техподдержка производителя, в сети достаточно решений типичных проблем на тематических форумах, EnSO и тут.
Для небольшого проекта острой необходимости в тяжелых фреймворках нет, более того, за счет отсутствия тяжелых и неповоротливых "монстров" небольшой проект даже выиграет, если не надумает расти конечно. В случае большого проекта все не так однозначно.
И да, это касается не только упомянутого вами MVVM, но и всех остальных областей, будь то WEB, работа с базами данных и т.д.

среда, 10 октября 2018 г.

Точка входа в MVVM: App.xaml.cs или представление?

Начал изучать MVVM и столкнулся, как наверное и многие другие, с определенным недопониманием. В многочисленных примерах реализации MVVM, доступных в сети, авторы разными способами подходят к точке входа в приложение (могу ошибаться в определении). Некоторые меняют аттрибут StartupUri, другие просто его полностью удаляют и в перегруженном методе OnStartup файла App.xaml.cs вручную создают экземпляр окна и устанавливают ему свойство DataContext. Нашел в сети несколько примеров по MVVM и mvvm-light (пример 1, пример 1, пример 3, пример 4 и пример 5) и в них автор вообще не изменяет App.xaml или App.xaml.cs и только в одном изменяет code-behind (так и не понял как это называется по-русски) представлений.
Мне ясно, что как и любой паттерн MVVM является рекомендацией и не запрещает отходить от правил в разумных пределах, но какая разница между этими подходами? Какие выгоды и подводные камни? Какой подход позволяет в дальнейшем более гибко расширять и сопровождать приложение (плагины, расширения и т.д.)?


Ответ

Я предпочитаю не использовать StartupUri, а переопределять OnStartup, и создавать главное окно там ([1], [2], [3]).
Причина в том, что указание StartupUri не позволяет задать DataContext снаружи окна. А хардкодирование DataContext'а внутри XAML неправильно, так как:
Согласно паттерну MVVM, View не должно руководить VM, и знать о нём должно как можно меньше. То есть код, обслуживающий UI, не должен создавать себе VM сам. Чаще всего VM должна получить ещё какие-то аргументы в конструкторе (например, модельные объекты), а это не получится сделать, если VM создаётся в XAML'е (откуда XAML может знать о модели?). Иногда перед открытием главного окна нужна дополнительная логика, требующая показа своего маленького окна (например, предложение обновить программу). Или нужн овыяснить, какое именно из окон нужно показывать в начале. Код, выясняющий это и при некоторых условиях показывающий дополнительное окно, проще разместить в OnStartup Главная VM может понадобиться вам для ещё чего-нибудь. Поэтому если её создаёт класс App, он может сохранить ссылку на неё у себя, чтобы другие (например, побочное окно) могли быть привязаны к тому же экземпляру VM. Иначе вам придётся лезть за главной VM в экземпляр главного окна.
В любом случае, MVVM не догма, делайте так, как вам удобнее.