Difference between revisions of "Property Direct Edit (Client)"
(→PropertyViewModel) |
(→PropertyViewModel) |
||
Line 124: | Line 124: | ||
{{Hint|Once again, you can use the [[Developer_Mode]] to find out more about the PropertyViewModel, like where they are available and how they can be accessed in XAML, or what other members are available underneath, etc.}} | {{Hint|Once again, you can use the [[Developer_Mode]] to find out more about the PropertyViewModel, like where they are available and how they can be accessed in XAML, or what other members are available underneath, etc.}} | ||
+ | |||
+ | === ValueItem.PropertyValue or ValueItem.PropertyValueSessionless {{Version/WinXSince|4.4}}{{Version/XamarinSince|4.4}} === | ||
+ | When it comes to property editing, there's the concept of edit sessions. A property editor always entails a session which starts when the editor is opened and ends when the editor is closed. | ||
+ | However, this could be different in direct editing. For example, | ||
+ | * The standard UI in {{UBIK}} for direct string editing still has sessions. The session starts when you click on the displayed value text and it turns into a text box for value input. It ends when you confirm the input value and the text box turns back into the displayed value text. | ||
+ | * On the other hand, the direct boolean editing is, for example, sessionless. This is because the UI displays a check box the entire time and there's no way to tell the start or the end of a session. | ||
+ | |||
+ | |||
+ | For most value types (e.g. where typing is involved during direct editing), the session concept still applies. '''ValueItem.PropertyValue''' should be used in bindings in such cases. Otherwise, the input values might be lost during editing. In other cases where direct editing is sessionless, '''ValueItem.PropertyValueSessionless''' should be used. Otherwise, the input value will be rejected since the property is technically speaking not in any edit session. | ||
+ | |||
+ | {{Hint|If you are unsure whether '''ValueItem.PropertyValue''' or '''ValueItem.PropertyValueSessionless''' should be used for a certain property type, go with the former. Because most types do have sessions in their direct editing UI. Also, the problem of misusing the former can be seen immediately, namely the editing doesn't work, whereas misusing the latter can lead to more issues that are hard to notice at first.}} | ||
[[Category:Client|Property Direct Edit (Client)]] | [[Category:Client|Property Direct Edit (Client)]] |
Revision as of 13:04, 16 June 2023
Overview
Property direct editing (also known as inline editing) aims to provide a more efficient way for users to edit properties, especially when such tasks are performed frequently.
Generally speaking, direct editing skips the additional dialogs or pages presented in regular editing and allows users to directly interact with the UI displaying properties. For example, a text box type of control can be used to both display the value of a property and accept modifications of the value from the user.
Supported property types
In UBIK®, we provide default templates for some most frequently used property types. However, you can use your own templates, controls, etc. as you like to deal with these property types or even more (as long as you can find suitable UI controls for dealing with these types).
UWP
They are accessible as DataTemplates from UBIKThemes.xaml (use the Developer Mode to find the default copy) and the syntax in XAML is {StaticResource TEMPLATE_NAME}
. Just like other such templates, they can be customized by overriding the DataTemplates with respective keys in UBIKThemes.xaml.
Xamarin
They are accessible as DataTemplates from UBIKThemes.xamlx and the syntax in XAML is {DynamicResource TEMPLATE_NAME}
. Just like such templates, they can be customized by providing your own DataTemplate resources (with the keys of TEMPLATE_NAME) in UBIKThemes.xamlx.
For Properties:
- String/Text: named as UBIKPropertyDirectItemString.
- Integer: named as UBIKPropertyDirectItemInt.
- Double: named as UBIKPropertyDirectItemDouble.
- Boolean: named as UBIKPropertyDirectItemBool.
- Guid: named as UBIKPropertyDirectItemGuid.
- DateTime: named as UBIKPropertyDirectItemDateTime.
- GeoData: named as UBIKPropertyDirectItemGeoData.
- With selective list items: named as UBIKPropertyDirectItemList.
Due to the limited screen size of most mobile devices, direct editing is not enabled by default in the Xamarin clients. |
For MRO-Tasks:
- String/Text: named as UBIKTaskPropertyString.
- Integer: named as UBIKTaskPropertyInt.
- Double: named as UBIKTaskPropertyDouble.
- Boolean: named as UBIKTaskPropertyBool.
- Guid: named as UBIKTaskPropertyGuid.
- DateTime: named as UBIKTaskPropertyDateTime.
- GeoData: named as UBIKTaskPropertyGeoData.
- With selective list items: named as UBIKTaskPropertyList.
Due to the limited screen size of most mobile devices, direct editing is not enabled by default for DateTime and GeoData types in the Xamarin clients. |
PropertyViewModel
This is the view model for every single UBIK® property and also the basement for property direct editing (and regular editing alike). For example, a certain named PropertyViewModel (with the name of PROPERTY_NAME) of the context object in a content page is accessible as {Binding Properties.VisibleItems[PROPERTY_NAME]}
.
In the example demonstrated in the screenshot where a test template is used to enable direct editing of a String/Text typed property, the following members of the PropertyViewModel are involved.
- InEditing: This is the boolean member indicating whether the PropertyViewModel is currently in edit mode. It can be used to decide whether the UI should display the DisplayValue text or present a text box for user input;
- Description: This is the description of the underlying property/meta property;
- ValueItem.PropertyValue: This is the value of property stored at the PropertyViewModel which can differ from the underlying property value because there can be editing changes not yet confirmed/saved. It can be read from and written to by the text box;
- DisplayValue: This is the textual version of ValueItem.PropertyValue used for displaying when the InEditing is false;
- StartDirectEditCommand: Sets InEditing to true and starts the direct editing session. In the example, this is linked to the tapped event of the entire template area;
- ConfirmEditCommand: Confirms the edit and sets InEditing to false. Even if the property value is not changed, this will give the property a new validation timestamp, technically modifying the property;
Optional command parameter for ConfirmEditCommand: ToValidate - Whether a validation timestamp should be added even if the value is unchanged when confirmed. Defaults to true if unspecified.
UWP
xmlns:uc="using:UBIK.WinX.Controls"
Command="{Binding ConfirmEditCommand}">
<Button.CommandParameter>
<uc:KeyValueList>
<uc:KeyValueParameter Key="ToValidate" Value="false" />
</uc:KeyValueList>
</Button.CommandParameter>
</Button>
Xamarin
xmlns:classes="clr-namespace:UBIK.CPL.Classes;assembly=UBIK.CPL"
Command="{Binding ConfirmEditCommand}">
<Button.CommandParameter>
<classes:KeyValueList>
<classes:KeyValueParameter Key="ToValidate" Value="false" />
</classes:KeyValueList>
</Button.CommandParameter>
</Button>
- SaveAndCommitCommand: In addition to confirming the edit, this also saves the changes to the underlying property, saves the owner object and attempts to commit it if the sync mode allows;
- ResetCommand: Resets the underlying property to its last known server state, saves the owner object and attempts to commit it if the sync mode allows;
- DeleteValueCommand: Sets the underlying property's value(s) to null and erases its validation timestamp, saves the owner object and attempts to commit it if the sync mode allows;
Optional command parameter for ResetCommand and DeleteValueCommand: AutoSave - Whether the change(s) to the property and the object should be saved right after the execution of these commands. Defaults to true if unspecified.
UWP
xmlns:uc="using:UBIK.WinX.Controls"
Command="{Binding DeleteValueCommand}">
<Button.CommandParameter>
<uc:KeyValueList>
<uc:KeyValueParameter Key="AutoSave" Value="false" />
</uc:KeyValueList>
</Button.CommandParameter>
</Button>
Xamarin
xmlns:classes="clr-namespace:UBIK.CPL.Classes;assembly=UBIK.CPL"
Command="{Binding DeleteValueCommand}">
<Button.CommandParameter>
<classes:KeyValueList>
<classes:KeyValueParameter Key="AutoSave" Value="false" />
</classes:KeyValueList>
</Button.CommandParameter>
</Button>
- DiscardChangeCommand: Discards all changes made at the PropertyViewModel level that are not yet saved to the underlying property;
- CancelEditCommand: Cancels the current editing session and discards all changes made at the PropertyViewModel level in that session (different from DiscardChangeCommand).
Once again, you can use the Developer Mode to find out more about the PropertyViewModel, like where they are available and how they can be accessed in XAML, or what other members are available underneath, etc. |
ValueItem.PropertyValue or ValueItem.PropertyValueSessionless
When it comes to property editing, there's the concept of edit sessions. A property editor always entails a session which starts when the editor is opened and ends when the editor is closed. However, this could be different in direct editing. For example,
- The standard UI in UBIK® for direct string editing still has sessions. The session starts when you click on the displayed value text and it turns into a text box for value input. It ends when you confirm the input value and the text box turns back into the displayed value text.
- On the other hand, the direct boolean editing is, for example, sessionless. This is because the UI displays a check box the entire time and there's no way to tell the start or the end of a session.
For most value types (e.g. where typing is involved during direct editing), the session concept still applies. ValueItem.PropertyValue should be used in bindings in such cases. Otherwise, the input values might be lost during editing. In other cases where direct editing is sessionless, ValueItem.PropertyValueSessionless should be used. Otherwise, the input value will be rejected since the property is technically speaking not in any edit session.
Relevant types
Here are some types created for the purpose of property direct editing.
PropertyDirectItemTemplateSelector
This is used in a ListView-like control where item templates should be specified, in this case property item templates specifically. It determines the different DataTemplates to be used for direct editing PropertyViewModels according to their property types. For types that have default UBIK® direct editing support, the template names follow the pattern of "UBIKPropertyDirectItemXXX" where XXX is the type name, e.g. String, DateTime, List, etc.
For types that do not come with default direct editing support, the selector uses the "UBIKPropertyItem" template in which editor dialogs are shown instead.
UWP
Namespace xmlns:tpl="using:UBIK.WinX.Templates"
Xamarin
Namespace xmlns:resources="clr-namespace:UBIK.CPL.Resources;assembly=UBIK.CPL"
TaskPropertyTemplateSelector
By default, MRO tasks have direct editing enabled for their task related properties in the "UBIKTaskItem" template. This template selector determines the different DataTemplates to be used for direct editing PropertyViewModels according to their property types. For types that have default UBIK® direct editing support, the template names follow the pattern of "UBIKTaskPropertyXXX" where XXX is the type name, e.g. String, DateTime, List, etc.
For types that do not come with default direct editing support, the selector uses the "UBIKTaskProperty" template in which editor dialogs are shown instead.
UWP
Namespace xmlns:tpl="using:UBIK.WinX.Templates"
Xamarin
Namespace xmlns:resources="clr-namespace:UBIK.CPL.Resources;assembly=UBIK.CPL"
ComboBoxItemTemplateSelector (UWP only)
By default, a ComboBox uses the same template for the selected item (when closed) as well as the drop down items (when opened), which is not always wanted. This template selector allows you to use different templates for these two types of items.
Namespace xmlns:tpl="using:UBIK.WinX.Templates"
- DropDownItemTemplate: for the dop down items (when opened)
- ComboBoxSectionItemTemplate: for the selected item (when closed)
Behaviors and controls
UWP
The KeyEventTriggerBehavior is a specialized version of the EventTriggerBehavior in the way that it sets the event to KeyDown by default and allows customizers to define which key (KeyName) should trigger the action(s).
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:behaviours="using:UBIK.WinX.Behaviors">
<Interactivity:Interaction.Behaviors>
<behaviours:KeyEventTriggerBehavior KeyName="Enter">
<Core:InvokeCommandAction Command="{Binding ConfirmEditCommand}" />
</behaviours:KeyEventTriggerBehavior>
<behaviours:KeyEventTriggerBehavior KeyName="Escape">
<Core:InvokeCommandAction Command="{Binding CancelEditCommand}" />
</behaviours:KeyEventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</TextBox>
Xamarin
The SelectAllEntry optionally accepts two commands (ReturnCommand & EscapeCommand) to execute when a user inputs the return key ↵ Enter and the escape key Esc respecitively.
<renderers:SelectAllEntry ...
ReturnCommand="{Binding ConfirmEditCommand}"
EscapeCommand="{Binding CancelEditCommand}" />
</Grid>
DateTime Control UWP
The CalendarControl and TimeControl both have an additional Event called "DateTimeChanged" that is called when confirming a value on the flyoutpickers.
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="DateTimeChanged">
<Core:InvokeCommandAction Command="{Binding PropertyViewModel.SaveAndCommitCommand}" />
</Core:EventTriggerBehavior>
<behaviours:KeyEventTriggerBehavior KeyName="Enter">
<Core:InvokeCommandAction Command="{Binding PropertyViewModel.ConfirmEditCommand}" />
</behaviours:KeyEventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</controls:UBIKCalendarControl>
<controls:UBIKTimeControl TimeString="{Binding ValueItem.PropertyValue.Time, Mode=TwoWay}">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="DateTimeChanged">
<Core:InvokeCommandAction Command="{Binding PropertyViewModel.SaveAndCommitCommand}" />
</Core:EventTriggerBehavior>
<behaviours:KeyEventTriggerBehavior KeyName="Enter">
<Core:InvokeCommandAction Command="{Binding PropertyViewModel.ConfirmEditCommand}" />
</behaviours:KeyEventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</controls:UBIKTimeControl>
DateTimeControl Xamarin
The CalendarControl has an additional Event called "DateSelected" that is called when confirming a value on the flyoutpickers. The TimeControl has a similar "TimeSelected" Event (Note that this event may have wrong behaviour on iOS)
<DatePicker.Behaviors>
<behaviors:EventToCommandBehavior EventName="DateSelected" Command="{Binding PropertyViewModel.ConfirmEditCommand}"/>
</DatePicker.Behaviors>
</DatePicker>
<ctrls:TimePickerExt Time="{Binding PropertyViewModel.ValueItem.PropertyValue.Time, Converter={StaticResource StringToDateTimeTypesConverter}">
<ctrls:TimePickerExt.Behaviors>
<behaviors:EventToCommandBehavior EventName="TimeSelected" Command="{Binding PropertyViewModel.ConfirmEditCommand}"/>
</ctrls:TimePickerExt.Behaviors>
</ctrls:TimePickerExt>