Jump to: navigation, search

Property Direct Edit (Client)


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). Direct editing properties also support Min Max Properties.

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.
IC Hint square.pngDue 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.
IC Hint square.pngDue 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]}.

A test template for direct editing a String property (Xamarin)
The same template now in edit mode (Xamarin)

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

  <Button ...
     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

  <Button ...
     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

  <Button ...
     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

  <Button ...
     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).
IC Hint square.pngOnce 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.

IC Hint square.pngIf 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.

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"

<tpl:ComboBoxItemTemplateSelector x:Key="ComboBoxItemTemplateSelector" DropDownItemTemplate="{StaticResource XXX}" ComboBoxSectionItemTemplate="{StaticResource XXX}" />
  • 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).

<TextBox ...
   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.

<Grid  xmlns:renderers="clr-namespace:UBIK.CPL.Platform.Renderers;assembly=UBIK.CPL">
    <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.

<controls:UBIKCalendarControl DateString="{Binding ValueItem.PropertyValue.Date, 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: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 Date="{Binding PropertyViewModel.ValueItem.PropertyValue.Date, Converter={StaticResource StringToDateTimeTypesConverter}">
   <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>