CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
Csla.Blazor/ViewModel.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="ViewModel.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Base type for creating your own viewmodel</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.Collections.Generic;
10using System.ComponentModel;
11using System.Linq.Expressions;
12using System.Threading.Tasks;
13using Csla.Reflection;
14using Csla.Rules;
15
16namespace Csla.Blazor
17{
21 public class ViewModel<T>
22 {
26 protected ApplicationContext ApplicationContext { get; private set; }
27
32 public ViewModel(ApplicationContext applicationContext)
33 {
34 ApplicationContext = applicationContext;
35 }
36
40 public event Action Saved;
44 public event Action<T, T> ModelChanging;
48 public event Action ModelChanged;
53 public event PropertyChangedEventHandler ModelPropertyChanged;
54
60 protected virtual void OnModelChanging(T oldValue, T newValue)
61 {
62 _info.Clear();
63 if (oldValue is INotifyPropertyChanged oldObj)
64 oldObj.PropertyChanged -= (s, e) => OnModelPropertyChanged(e.PropertyName);
65 if (newValue is INotifyPropertyChanged newObj)
66 newObj.PropertyChanged += (s, e) => OnModelPropertyChanged(e.PropertyName);
67 ModelChanging?.Invoke(oldValue, newValue);
68 }
69
73 protected virtual void OnModelChanged()
74 {
75 ModelChanged?.Invoke();
76 }
77
82 protected virtual void OnModelPropertyChanged(string propertyName)
83 {
84 ModelPropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
85 }
86
91 public async Task<T> RefreshAsync(Func<Task<T>> factory)
92 {
93 Exception = null;
94 ViewModelErrorText = null;
95 try
96 {
97 Model = await factory();
98 }
99 catch (DataPortalException ex)
100 {
101 Model = default;
102 Exception = ex;
104 }
105 catch (Exception ex)
106 {
107 Model = default;
108 Exception = ex;
109 ViewModelErrorText = ex.Message;
110 }
111 return Model;
112 }
113
118 public async Task SaveAsync()
119 {
120 Exception = null;
121 ViewModelErrorText = null;
122 if (Model is Core.ITrackStatus obj && !obj.IsSavable)
123 {
125 return;
126 }
127 try
128 {
129 Model = await DoSaveAsync();
130 Saved?.Invoke();
131 }
132 catch (DataPortalException ex)
133 {
134 Exception = ex;
136 }
137 catch (Exception ex)
138 {
139 Exception = ex;
140 ViewModelErrorText = ex.Message;
141 }
142 }
143
148 protected virtual async Task<T> DoSaveAsync()
149 {
150 if (Model is Core.ISavable savable)
151 {
152 var result = (T)await savable.SaveAsync();
153 if (Model is Core.IEditableBusinessObject editable)
154 new Core.GraphMerger(ApplicationContext).MergeGraph(editable, (Core.IEditableBusinessObject)result);
155 else
156 Model = result;
157 }
158 return Model;
159 }
160
161 private T _model;
165 public T Model
166 {
167 get => _model;
168 set
169 {
170 if (!ReferenceEquals(_model, value))
171 {
172 OnModelChanging(_model, value);
173 _model = value;
175 }
176 }
177 }
178
179 private readonly Dictionary<string, object> _info = new Dictionary<string, object>();
180
188 public IPropertyInfo GetPropertyInfo<P>(Expression<Func<P>> property)
189 {
190 if (property == null)
191 throw new ArgumentNullException(nameof(property));
192
193 var keyName = property.GetKey();
194 var identifier = Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create(property);
195 return GetPropertyInfo(keyName, identifier.Model, identifier.FieldName);
196 }
197
206 public IPropertyInfo GetPropertyInfo<P>(Expression<Func<P>> property, string id)
207 {
208 if (property == null)
209 throw new ArgumentNullException(nameof(property));
210
211 var keyName = property.GetKey() + $"[{id}]";
212 var identifier = Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create(property);
213 return GetPropertyInfo(keyName, identifier.Model, identifier.FieldName);
214 }
215
223 public IPropertyInfo GetPropertyInfo(string propertyName)
224 {
225 var keyName = Model.GetType().FullName + "." + propertyName;
226 return GetPropertyInfo(keyName, Model, propertyName);
227 }
228
237 public IPropertyInfo GetPropertyInfo(string propertyName, string id)
238 {
239 var keyName = Model.GetType().FullName + "." + propertyName + $"[{id}]";
240 return GetPropertyInfo(keyName, Model, propertyName);
241 }
242
243 private IPropertyInfo GetPropertyInfo(string keyName, object model, string propertyName)
244 {
245 PropertyInfo result;
246 if (_info.TryGetValue(keyName, out object temp))
247 {
248 result = (PropertyInfo)temp;
249 }
250 else
251 {
252 result = new PropertyInfo(model, propertyName);
253 _info.Add(keyName, result);
254 }
255 return result;
256 }
257
261 public string ViewModelErrorText { get; protected set; }
262
267 protected virtual string ModelErrorText
268 {
269 get
270 {
271 if (Model is IDataErrorInfo obj)
272 {
273 return obj.Error;
274 }
275 return string.Empty;
276 }
277 }
278
284 public Exception Exception { get; private set; }
285
292 public bool CanCreateObject()
293 {
295 }
296
303 public bool CanGetObject()
304 {
306 }
307
314 public bool CanEditObject()
315 {
317 }
318
325 public bool CanDeleteObject()
326 {
328 }
329 }
330}
Provides consistent context information between the client and server DataPortal objects.
Exposes metastate for a property.
Base type for creating your own viewmodel.
Action< T, T > ModelChanging
Event raised when Model is changing
async Task SaveAsync()
Saves the Model
async Task< T > RefreshAsync(Func< Task< T > > factory)
Refresh the Model
string ViewModelErrorText
Gets any error text generated by refresh or save operations
virtual string ModelErrorText
Gets the first validation error message from the Model
PropertyChangedEventHandler ModelPropertyChanged
Event raised when the Model object raises its PropertyChanged event
bool CanEditObject()
Gets a value indicating whether the current user is authorized to edit/save an instance of the busine...
virtual void OnModelChanged()
Raises the ModelChanged event
virtual async Task< T > DoSaveAsync()
Override to provide custom Model save behavior
IPropertyInfo GetPropertyInfo< P >(Expression< Func< P > > property)
Get a PropertyInfo object for a property.
Exception Exception
Gets the last exception caught by the viewmodel during refresh or save operations.
virtual void OnModelChanging(T oldValue, T newValue)
Raises the ModelChanging event
IPropertyInfo GetPropertyInfo(string propertyName)
Get a PropertyInfo object for a property of the Model.
ViewModel(ApplicationContext applicationContext)
Creates an instance of the type.
T Model
Gets or sets the Model object.
bool CanGetObject()
Gets a value indicating whether the current user is authorized to retrieve an instance of the busines...
Action ModelChanged
Event raised when Model has changed
virtual void OnModelPropertyChanged(string propertyName)
Raises the ModelPropertyChanged event
bool CanCreateObject()
Gets a value indicating whether the current user is authorized to create an instance of the business ...
bool CanDeleteObject()
Gets a value indicating whether the current user is authorized to delete an instance of the business ...
Action Saved
Event raised after Model has been saved
IPropertyInfo GetPropertyInfo(string propertyName, string id)
Get a PropertyInfo object for a property of the Model.
This exception is returned for any errors occurring during the server-side DataPortal invocation.
string BusinessExceptionMessage
Gets the Message property from the BusinessException, falling back to the Message value from the top-...
Maintains metadata about a property.
Tracks the business rules for a business object.
static bool HasPermission(ApplicationContext applicationContext, AuthorizationActions action, Type objectType)
Checks per-type authorization rules.
Exposes metastate for a property.
AuthorizationActions
Authorization actions.