Vibrant discussion about CSLA .NET and using the framework to build great business applications.
Hi, I'm looking to implement an 'Edit' mode for our WPF UI - in other words, the controls on the form bound to the business object should not be available until the user clicks an 'edit' button. At which point the 'edit' button should become disabled, and a 'save' button enabled (once the data has changed, and the BO is dirty).
What would be the recommended approach for this? It seems as though an Edit method and Editable boolean property should be added to a custom ViewModel<T> derived from ViewModelBase<T>. However, we are also using the CSLA PropertyStatus control to perform our form validations, and therefore we would want each control (TextBoxes, ComboBoxes etc) to be disabled until this 'Edit' button has been clicked.
I don't want to modify the CSLA.NET core code, so I'm wondering what might be the best approach?
Are you allowing PropertyStatus to set the IsReadOnly/IsEnabled properties of your UI controls?
I would stop doing that (I don't use that feature of PropertyStatus anymore personally), because it won't help you solve your problem.
Notice though, that PropertyStatus exposes properties you can use to turn on/off your UI control through binding. So the IsEnabled property of your UI control can bind to the CanWrite property of the PropertyStatus (for example).
If you are already doing that, then the next steps will be easier (possible).
Xaml binding has a thing called a multivalue converter. This allows you to take multiple input values, and basically merge them into one output value. I suspect that you can use a multivalue converter to solve your problem.
Bind your UI control's IsEnabled property to a multivalue converter that generates its value from both the PropertyStatus CanWrite and viewmodel EditMode properties. Basically the converter would only return true if both input properties are true.
That way you leverage both the per-property authz features of your object, and the per-form feature of your edit button.
Thanks Rocky, that was the sort of thing I was looking for. However, I'm not sure that we could justify a multi value converter for every control on the form. Therefore, I'm wondering if rolling our own PropertyStatus control might be the way to go. That way, I can rework HandleTarget() to check the EditMode property of the current DataContext, or also add an additional EditMode property to the PropertyStatus control which can bind to the EditMode property of the ViewModel in XAML.
We also want to set the MaxLength property of TextBox controls based on the validation rules (StringMaxLength) of the bound BO. Therefore, this logic can also go in HandleTarget.
My only concern with this approach is that we will have to track and migrate any changes/fixes to your PropertyStatus control across to ours on each new release. Do you plan on making your PropertyStatus control more tailored for people making their own custom versions?
I hadn't planned on changing PropertyStatus to be more extensible, no.
Why don't you try your idea by creating a subclass and just changing PropertyStatus as little as possible (maybe making a couple things virtual or whatever). If the required changes to PropertyStatus are minor you and I can discuss what they are and I'll consider working them into the codebase.
Thanks Rocky, am I correct in saying that PropertyStatus only checks property level authorization rules, and not type level authorization? Is this by design? If that's the case, how could I retrieve the object type within HandleTarget() to pass to Csla.Security.AuthorizationRules.CanEditObject() ? I would like to check type level authorization and then property level authorization, or is this functionality already built into CanWriteProperty() called by HandleTarget() ?
CslaDataProvider and ViewModelBase check type level authz rules.
It isn't clear to me how property level rules would be affected by the per-type rules. The per-type rules control whether the user is allowed to do create/fetch/save/delete operations. A given user might be able to create a new object, but not edit existing ones - so they'd still need to edit some or all of the properties.
The idea is that you'll use both concepts together. If a user isn't allowed to edit an object at all, then you'd probably set their role so it can't edit any properites, can't create the type or save or delete the type. But they'd presumably still be able to get/fetch the type.
Hi Rocky, I've implemented my own PropertyStatus control by creating a derived type from yours (with a few minor changes to your code). I will send these changes across when everything is complete, but I am now at the stage where I wish to set the MaxLength property of TextBox controls based on the validation rules of the BO. Do you have any thoughts on how these could be accessed externally from the BO?
If you use the DataAnnotations attributes there's a length attribute you can use. CSLA honors those attributes, and your PropertyStatus subclass could reflect against the property to get the attribute, and then expose its own MaxLength property so the UI can bind to that value.
I managed to create a custom PropertyStatus control derived from your type, with just the following changes:
private object _source = null; changed to protected object _source = null; private string _bindingPath = string.Empty; changed to protected string _bindingPath = string.Empty;private bool _isReadOnly = false; changed to protected bool _isReadOnly = false;CanRead and CanWrite setters changed from private to protectedprivate void HandleTarget changed to protected virtual HandleTargetprivate void GoToState(bool useTransitions) changed to protected virtual void GoToState(bool useTransitions)
If these changes could be incorporated into a future version of PropertyStatus, it would be very helpful!