System.Windows.Expression:
public class System.Windows.Expression:
//“This type supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code”.
{Binding HasErrors, Converter={StaticResource InverseBooleanConverter}}
{Binding !HasErrors}
EventToCommand
class for this purpose.UpdateSourceTrigger=PropertyChanged
). On the WinRT platform, this opportunity returned, but the ValidatesOnExceptions
and ValidatesOnNotifyDataErrors
properties that are responsible for validation disappeared, and the StringFormat
property, which is responsible for formatting the result, disappeared.??, ?:, +, -, *, /, %, , ==, !=, <, >, <=, >=, &&(and), ||(or), |, &, !, ~
), the priority of operations is taken into account in accordance with the C # language standard. Lambda expressions, output of generic types based on values, method call, extension method call, Linq are supported.TargetPath SourcePath, Mode=TwoWay, Validate=true
TargetPath
- the path for the Binding of the control.SourcePath
- the path for the Binding from a data source or a C # language expression, you can use several paths.Mode, Validate
- advanced options for Binding, such as Mode, Fallback, Delay
, etc.$self
- returns the current control to which the Binding is installed, the {RelativeSource Self}
equivalent.$root
- returns the current root element for which the Binding is set.$context
- returns the current DataContext
for Binding, the equivalent of {RelativeSource Self, Path=DataContext}
.$args
- returns the current parameter EventArgs
, can be used only if the TargetPath
indicates an event. Text Property, Mode=TwoWay, Validate=True Text Items.First(x => x == Name).Value + Values.Select(x => x.Value).First(x => x == Name), Fallback='empty' Text $string.Format('{0} {1}', Prop1, Prop2), Delay=100 Text $string.Join($Environment.NewLine, $GetErrors()), TargetDelay=1000 Text Property.MyCustomMethod() Text Prop1 ?? Prop2 Text $CustomMethod(Prop1, Prop2, 'string value') Text Prop1 == 'test' ? Prop2 : 'value'
EventArgs
parameter using the $args
keyword. TextChanged EventMethod($args.UndoAction) TextChanged EventMethodMultiParams(Text, $args.UndoAction)
INotifyDataErrorInfo
interface. Each platform will display an error message. Text Property, Mode=TwoWay, ValidatesOnNotifyDataErrors=True Text Property, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True Text Property, Mode=TwoWay, Validate=True // ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True
Enabled = false
) if the command cannot be executed. Click Command, ToggleEnabledState=false // Click Command, ToggleEnabledState=true //
$GetErrors()
method will return validation errors of the entire form for all properties or errors for specific properties. The method is useful when there is a need to show the user errors on the form. Text $GetErrors(Property).FirstOrDefault() Text $string.Join($Environment.NewLine, $GetErrors()) // , .
RelativeSource
property for XAML platforms).$Element(ElementName)
- searches for an element with the name ElementName.$Relative(Type), $Relative(Type, 1)
- searches among the parent control elements with the Type
type and (if necessary) taking into account the level of the parent element (second parameter).$self
- returns the current element on which the Binding is set. Text $Relative(Window).Title Text $self.ActualWidth Text $Element(NamedSlider).Value
DataGridView
does not have a SelectedItem
property, but we can easily add it using the attached property: var member = AttachedBindingMember.CreateMember<DataGridView, object>("SelectedItem", (info, view) => { var row = view.CurrentRow; if (row == null) return null; return row.DataBoundItem; }, (info, view, item) => { view.ClearSelection(); if (item == null) return; for (int i = 0; i < view.Rows.Count; i++) { if (Equals(view.Rows[i].DataBoundItem, item)) { var row = view.Rows[i]; row.Selected = true; } } }, "CurrentCellChanged"); //CurrentCellChanged - DataGridView, . // BindingServiceProvider.MemberProvider.Register(member);
// MyResourceObject i18n BindingServiceProvider.ResourceResolver.AddObject("i18n", new BindingResourceObject(new MyResourceObject())); // Binding Text $i18n.MyResourceString
var textBox = new TextBox(); var set = new BindingSet<TextBox, MainViewModel>(textBox); set.Bind(window => window.Text).To(vm => vm.Property).TwoWay(); set.Apply();
INotifyPropertyChanged
interface.ICommand
interface.Messenger
class that allows you to exchange messages between classes.ViewModel
regardless of platform.ViewModel
, via a constructor with dependencies and parameters.ViewModel
and View
.ViewModel
state management depending on the View
life cycle.ViewModel
state depending on the platform.ViewModel
code for different platforms.IIocContainer
interface is used for interaction. Currently, there are implementations for the three DI containers MugenInjection
, Autofac
, Ninject
. The list can be expanded by adding the IIocContainer
interface IIocContainer
for any other container.ViewModel
, for different situations.ViewModelBase
- the base class for all ViewModel
, contains methods for creating other ViewModel
, methods for exchanging messages, methods and properties IsBusy
, BusyMessage
for managing the state of asynchronous operations.CloseableViewModel
- inherited from ViewModelBase
, implements the ICloseableViewModel
interface, which allows you to manage the process of closing the ViewModel
.ValidatableViewModel
- ValidatableViewModel
from CloseableViewModel
, contains methods and properties for validation, implements the INotifyDataErrorInfo
interface for notifying Binding about errors.EditableViewModel<T>
- inherits from ValidatableViewModel
, allows you to edit and validate the data model, monitors the state of the object, and allows you to undo the changes.WorkspaceViewModel, WorkspaceViewModel<TView>
- inherits from CloseableViewModel
, contains the properties IsSelected
and DisplayName
- for convenient display of the ViewModel
in the interface. Implements the IViewAwareViewModel<TView>
interface, which allows access to the View
via the IView
interface. Implements the INavigableViewModel
interface, which allows you to track the navigation process for the ViewModel
, OnNavigatedFrom
, OnNavigatingFrom
, OnNavigatedTo
.GridViewModel
- inherited from ViewModelBase
, allows you to work with collections of various objects.MultiViewModel
- inherited from CloseableViewModel
, allows you to work with the collections of other ViewModel
, well suited for binding to TabControl
.ViewModelLocator
to create a ViewModel
. All ViewModel
are created using the DI container, the IViewModelProvider
interface is responsible for creating the ViewModel
. public class ItemViewModel : ViewModelBase { public ItemViewModel(ISomeService service) { } public void InitializeValue() { } } public class MainViewModel : ViewModelBase { public void CreateViewModelMethod() { // ViewModel var viewModel = GetViewModel<ItemViewModel>(); // , , .. viewModel.InitializeValue(); } }
View
with ViewModel
occurs dynamically. The IViewMappingProvider
interface is responsible for IViewMappingProvider
, and the default naming convention is used. The following endings are removed for the ViewModel
:"ViewModel", "Vm"
,View
:"ActivityView", "FragmentView", "WindowView", "PageView", "FormView", "Form", "View", "V", "Activity", "Fragment", "Page", "Window"
View
corresponds to the ViewModel
.MainViewModel, MainVm -> MainActivityView, MainFragmentView, MainWindowView ..
View
for the ViewModel
, you can use the ViewModelAttribute
(in this case, the naming convention is ignored): [ViewModel (typeof(MainViewModel))] public partial class MainWindow : Window
View
and then use it when creating / displaying the ViewModel
: [ViewModel (typeof(ItemViewModel), “ViewName”)] public partial class ItemView : Window // ViewModel View // ViewModel View ViewName var viewModel = GetViewModel<ItemViewModel>(parameters: NavigationConstants.ViewName.ToValue("ViewName")); // ViewModel var viewModel = GetViewModel<ItemViewModel>(); // , ViewModel View ViewName viewModel.ShowAsync(NavigationConstants.ViewName.ToValue("ViewName"));
ViewModel
state. If the ViewModel
has a state to save, it must implement the IHasState
interface, which has two methods LoadState
and SaveState
. The system will automatically call these methods depending on the life cycle of the application and the current platform. private static readonly DataConstant<string> StringState = DataConstant.Create(() => StringState, true); public void LoadState(IDataContext state) { // state.AddOrUpdate(StringState, "Constant key"); // state.AddOrUpdate("Test", "String key"); } public void SaveState(IDataContext state) { string data = state.GetData(StringState); var s = state.GetData<string>("Test"); }
ViewModel
. Navigation in MVVM is one of the most difficult topics, including displaying dialog boxes, adding tabs to TabControl
, showing pages for mobile applications, etc. This topic is difficult because on different platforms the same ViewModel
can be a dialog box, Page
(WinRT, WP, WPF, SL), Activity
, Fragment
(Android), ViewController
(iOS), etc. At the same time, the API for working with the ViewModel
should look the same regardless of the platform, since for ViewModel
no difference how to display yourself. // var mainWindow = new MainWindow(); // . mainWindow.Init(args); if (!mainWindow.ShowDialog().GetValueOrDefault()) return; // , .
// Activity, , . var page2 = new Intent (this, typeof(Page2)); // page2.PutExtra ("arg1", arg) StartActivity (page2); // , , Activity
// Android. NavigationService.Navigate(typeof(Page2), arg);
MvvmCross
: ShowViewModel<DetailViewModel>(new DetailParameters() { Index = 2 });
DetailViewModel
must have an Init
method that accepts the DetailParameters
class: public void Init(DetailParameters parameters) { // use the parameters here }
DetailParameters
object must be serializable, therefore no complex objects can be transferred. With this approach, it is also very difficult to get the result from the DetailViewModel
after the navigation is completed. The approach in MvvmCross is very similar to standard navigation for mobile platforms. You specify the type of the ViewModel
, the parameter being serializable and the system displays the View
and associates it with the ViewModel
. At the same time, it is quite difficult to find out from one ViewModel
when another ViewModel
was closed. All these restrictions are due to the fact that on mobile devices your application can be completely unloaded from memory, and then restored again, and then there is a problem with saving and restoring state. Basically, this problem is solved by saving the navigation path and serializing the navigation parameters so that they can be restored later.ViewModel
closed. Consider an example, you need from Vm1
, show Vm1
and process the result after Vm1
closed, while it does not matter which platform and which display will be on Vm2
: public class Vm2 : ViewModelBase { public void InitFromVm1() { } public object GetResult() { return null; } } public class Vm1 : ViewModelBase { public async void Open() { var vm2 = GetViewModel<Vm2>(); // , . vm2.InitFromVm1(); // IAsyncOperation, // Vm2 IAsyncOperation<bool> asyncOperation = vm2.ShowAsync(Vm2CloseCallback); // asyncOperation.ContinueWith(Vm2CloseCallback); // await await asyncOperation; // Vm2 // var result = vm2.GetResult(); } private void Vm2CloseCallback(IOperationResult<bool> operationResult) { // var result = ((Vm2)operationResult.Source).GetResult(); } private void Vm2CloseCallback(Vm2 vm2, IOperationResult<bool> operationResult) { // var result = vm2.GetResult(); } }
Vm2
displayed, and even if your application is unloaded from memory, all registered delegates and state machines will also be saved and then restored. If you want to use async / await on a WinRT or Windows Phone platform, you will need to install a plugin for Fody , this is due to the limitations of reflection for these platforms.Window
to any ViewModel
, then when you call the ShowAsync
method, a dialog box will be shown.ChildWindow
class for SL. If you associate ChildWindow
with any ViewModel
, then when you call the ShowAsync
method, a dialog box will be shown.NavigationWindow
, for SL - Frame
.DataBindingExtension
class and the attached property View.Bind
. <TextBlock Text="{DataBinding 'Text.ExtensionMethod(Text.Count())'}" /> <TextBlock Text="{DataBinding '$string.IsNullOrEmpty(Text) ? \'String is empty\' : \'String is not empty\''}"/> <TextBlock View.Bind="Text Text.ExtensionMethod(Text.Count())"/> <TextBlock View.Bind="Text $string.IsNullOrEmpty(Text) ? 'String is empty' : 'String is not empty'"/> <Button Click="{DataBinding Path=Command, ToggleEnabledState=False}" /> <Button View.Bind="Click Command, ToggleEnabledState=False" /> <TextBox TextChanged="{DataBinding 'EventMethodMultiParams($self.Text, $args.UndoAction)'}" /> <TextBox View.Bind="TextChanged EventMethodMultiParams($self.Text, $args.UndoAction)" />
Page
class. If you match Page
with any ViewModel
, then when you call the ShowAsync
method, a new page will be shown.View.Bind
attached property View.Bind
. To use it, you must add a namespace: xmlns:markupExtensions="clr-namespace:MugenMvvmToolkit.MarkupExtensions;assembly=MugenMvvmToolkit.WinPhone" xmlns:markupExtensions="using:MugenMvvmToolkit.MarkupExtensions"
<TextBlock markupExtensions:View.Bind="Text Text.ExtensionMethod(Text.Count())"/> <TextBlock markupExtensions:View.Bind="Text $string.IsNullOrEmpty(Text) ? 'String is empty' : 'String is not empty'"/> <Button markupExtensions:View.Bind="Click Command, ToggleEnabledState=False" /> <TextBox markupExtensions:View.Bind="TextChanged EventMethodMultiParams($self.Text, $args.UndoAction)" />
DataTemplateSelector
for Binding support, analog DataTemplateSelector
for Xaml platforms.Form
class. If you map a Form
to any ViewModel
, then when you call the ShowAsync
method, a dialog box will be shown.System.Windows.Forms.ErrorProvider
class. public class ViewBinder : Binder { public ViewBinder() { } public ViewBinder(IContainer container) : base(container) { } }
ViewBinder
class should appear ViewBinder
Bindings
property. <Bindings> <addToolStripButton Click="AddNodeCommand" /> <removeToolStripButton Click="RemoveNodeCommand" /> <treeView ItemsSource="Nodes" CollectionViewManager="$treeNodeCollectionViewManager" ItemTemplate="$treeNodeTemplate" SelectedNode.DataContext="SelectedNode, Mode=OneWayToSource" /> <nameTextBox Text="SelectedNode.Name, Mode=TwoWay, Fallback='Nothing selected'" /> <validCheckBox Checked="SelectedNode.IsValid, Mode=TwoWay" /> </Bindings>
Activity
, for all standard Activity
there is an implementation with the prefix Mvvm, to work you need to inherit not from the standard Activity
, but with the prefix Mvvm. If you compare Activity
with any ViewModel
, then when you call the method ShowAsync
, you will be navigated to a new Activity
type.Fragment
, for all standard Fragment
there is an implementation with the prefix Mvvm, to work you need to inherit not from the standard Fragment
, but with the prefix Mvvm. If you compare MvvmDialogFragment
with any ViewModel
, then when the method is called ShowAsync
, a dialog box will be displayed.Activity
Fragment
. Activity
Fragment
, / ViewModel
.back stack fragment
.xmlns:pkg="http://schemas.android.com/apk/res-auto"
, Binding Bind
<ListView android:layout_width="fill_parent" android:layout_height="wrap_content" pkg:ItemTemplate="@layout/_itemlistviewtemplate" pkg:Bind="ItemsSource Items"/>
ActionBar
, Toolbar
, PopupMenu
OptionsMenu
.DataTemplateSelector
Binding, DataTemplateSelector
Xaml .TextView.Error
. <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" pkg:Bind="Text $Format('Name: {0}, Id: {1}', Name, Id)" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" pkg:Bind="Click Command" />
UIViewController
, UIViewController
Mvvm, UIViewController
, Mvvm. UIViewController
- ViewModel
, ShowAsync
, UIViewController
.UIViewController
.UIViewController
. UIViewController
, / ViewModel
.DataTemplateSelector
Binding, DataTemplateSelector
Xaml .MonoTouch.Dialog
.Page
. Page
- ViewModel
, ShowAsync
, .Page
.DataBindingExtension
attached property View.Bind
, Binding. Binding Xaml- xmlns:mugen="clr-namespace:MugenMvvmToolkit.MarkupExtensions;assembly=MugenMvvmToolkit.Xamarin.Forms"
<Entry Text="{mugen:DataBinding Name, Mode=TwoWay, Validate=True}" /> <Button Command="{mugen:DataBinding $Relative(ListView).DataContext.ShowCommand}" Text="{mugen:DataBinding Item1}" CommandParameter="{mugen:DataBinding Item2}" />
Source: https://habr.com/ru/post/236745/
All Articles