Обзор c# wpf mvvm
DESCRIPTION
Обзор C# WPF MVVM для студентов БФУ им. И. Канта в рамках Winter Coding School 06.02.2014TRANSCRIPT
Неолант
C# WPF MVVM
Мария Нащанскаяведущий программист
Литература«Совершенный код» Стив Макконнелл
«Deadline. Роман об управлении проектами» Том ДеМарко
Джеффри Рихтер «CLR via C#» «Программирование на платформе Microsoft.NET Framework 4.5 на языке C#»
Эндрю Троелсен «Язык программирования C# 5.0 и платформа .NET 4.5»
Адам Натан «WPF 4. Unleashed» (Подробное руководство)
Мэтью Макдональд
«Художественная»
C#
WPF
С#public class Person: BaseClass, IClonable, ICommand { private static const cUni = «BFU»; ! //свойство private string mName; public string Name { get { return mName; } set { mName = value; } } //свойство public string Surname { get; set;} }
Наследование!public abstract class Animal { public virtual int LegsCount() { return 4; } ! public abstract string Say(); }
public class Human: Animal { public override int LegsCount() { return 2; } ! public override string Say() { return «Hello»; } }
Human john = new Human(); string firstWord = john.Say();Animal someone = john; int legsCount = john.LegsCount();
Интерфейсыpublic interface ICommand { string CommandName { get; } ! void Execute; }
public class MyCommand: ICommand { public string CommandName { get { return «MyFirstCommand»; } } public void Execute() { Console.Writeln(«HelloWorld»): }}
List<ICommand> commands = OurSmartClass.GetCommands(); foreach (var command in commands) { command.Execute(); }
События и делегатыpublic class SmartClass { public delegate void Action (string option); ! public event Action SomethingHappens; ! private void SmartOperation() { if ( SomethingHappens!=null ) //есть ли подписчики SomethingHappens(«error»); } } SmartClass ourClass = new SmartClass(); ourClass.SomethingHappens += ReactOnEvent;private void ReactOnEvent (string option) {}
WPF. XAMLCustomerView.xaml CustomerView.xaml.cs
TextBox Button
ComboBoxGrid
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="6"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="30"/> <RowDefinition Height="Auto"/> <RowDefinition Height="30"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> </Grid>
Label
code behind пуст
<Label Content = "Customer type:" Grid.Row = "0" Grid.Column = "0" HorizontalAlignment = "Right"/>
<TextBox Text = "{Binding Path = FirstName}" Grid.Row = "2" Grid.Column = "2"/>
<ComboBox ItemsSource = "{Binding Path = CustomerTypeOptions, Mode = OneTime}" SelectedItem = "{Binding Path = CustomerType}"/>
<Grid Margin = "4">
</Grid>
<Button Content = "Save" Grid.Row = "8" Grid.Column = "2" HorizontalAlignment = "Right" Command = "{Binding Path = SaveCommand}"/>
<Grid.RowDefinitions … /><Grid.ColumnDefinitions … />
CustomerView.xaml
MVVMhttp://bit.ly/1k2Q6sYmsdn о MVVM Pattern:
Events
View ViewModel Model
Прямая связь только так:Чтобы не было соблазна, создавайте три разных проекта (Project) в одном
Solution: !OurProgram.View
OurProgram.ViewModel OurProgram.Model
Data Binding - привязка данныхpublic class MainViewModel : BaseViewModel !{ private string mFavoriteColor; ! public string FavoriteColor { get { return mFavoriteColor; } set { if (value != mFavoriteColor) { mFavoriteColor = value; OnPropertyChanged("FavoriteColor"); } } } }
Чтобы View узнало об изменениях в ViewModel
INotifyPropertyChangedpublic class BaseViewModel : INotifyPropertyChanged !{ #region INotifyPropertyChanged members ! public event PropertyChangedEventHandler PropertyChanged; ! protected virtual void OnPropertyChanged (string propertyName) ! { ! if (PropertyChanged != null) ! { ! var e = new PropertyChangedEventArgs (propertyName); ! PropertyChanged (this, e); ! } ! } ! #endregion !}
App.xaml.cs DataContext
public partial class App : Application !{ protected override void OnStartup(StartupEventArgs e) { ! base.OnStartup(e); ! MainWindow window = new MainWindow(); ! var viewModel = new MainViewModel(); ! window.DataContext = viewModel; ! window.Show(); ! } !}
ICommandpublic class MyCommand : ICommand !{ #region ICommand members ! public bool CanExecute (object parameter) { … //если команда используется для Button, то при false Button будет не активна ! } ! public void Execute (object parameter) ! { … ! } ! public event EventHandler CanExecuteChanged { ! add { CommandManager.RequerySuggested += value; } ! remove { CommandManager.RequerySuggessted -= value; } ! } ! #endregion !}
Использование RelayCommandpublic class CustomerViewModel: BaseViewModel !{ private ICommand mSaveCommand; ! public ICommand SaveCommand { get { if (mSaveCommand == null) { mSaveCommand = new RelayCommand( param => this.Save(), param => this.CanSave()); } return mSaveCommand; } } ! private void Save() {} private bool CanSave() {} !}
Data Validation - IDataErrorInfopublic class CustomerViewModel: BaseViewModel, IDataErrorInfo !{ public string IDataErrorInfo.Error { get { return (_customer as IDataErrorInfo).Error; } } ! public string IDataErrorInfo.this[string propertyName] { get { string error = null; if (propertyName == "CustomerType") error = this.ValidateCustomerType(); else error = (_customer as IDataErrorInfo)[propertyName]; ! CommandManager.InvalidateRequerySuggested(); return error; } } ! private string ValidateCustomerType() { if (this.CustomerType == Strings.CustomerViewModel_CustomerTypeOption_Company || this.CustomerType == Strings.CustomerViewModel_CustomerTypeOption_Person) return null; return Strings.CustomerViewModel_Error_MissingCustomerType; } }
IDataErrorInfo, xaml!
<Grid> <Grid.Resources> <DataTemplate DataType="{x:Type ValidationError}"> <TextBlock FontStyle="Italic" Foreground="Red" HorizontalAlignment="Right" Margin="0,1" Text="{Binding Path=ErrorContent}" /> </DataTemplate> </Grid.Resources> ! <ComboBox x:Name="customerTypeCmb" Grid.Row="0" Grid.Column="2" ItemsSource="{Binding Path=CustomerTypeOptions, Mode=OneTime}" SelectedItem="{Binding Path=CustomerType, ValidatesOnDataErrors=True}" Validation.ErrorTemplate="{x:Null}"/> ! <ContentPresenter Grid.Row="1" Grid.Column="2" Content="{Binding ElementName=customerTypeCmb, Path=(Validation.Errors).CurrentItem}" /> !
!