diff --git a/UnityWeld/Binding/Adapters/StringArrayToListAdapter.cs b/UnityWeld/Binding/Adapters/StringArrayToListAdapter.cs
new file mode 100644
index 0000000..8654a08
--- /dev/null
+++ b/UnityWeld/Binding/Adapters/StringArrayToListAdapter.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+
+namespace UnityWeld.Binding.Adapters
+{
+ ///
+ /// Adapter for converting from a string array to a string list.
+ ///
+ [Adapter(typeof(string[]), typeof(List), null)]
+ public class StringArrayToListAdapter : IAdapter
+ {
+ public object Convert(object valueIn, AdapterOptions options)
+ {
+ List output = new List();
+
+ if(valueIn == null)
+ {
+ return output;
+ }
+ return new List((string[])valueIn);
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityWeld/Binding/Adapters/StringListToArrayAdapter.cs b/UnityWeld/Binding/Adapters/StringListToArrayAdapter.cs
new file mode 100644
index 0000000..01e6cbf
--- /dev/null
+++ b/UnityWeld/Binding/Adapters/StringListToArrayAdapter.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+
+namespace UnityWeld.Binding.Adapters
+{
+ ///
+ /// Adapter for converting from a string list to a string array.
+ ///
+ [Adapter(typeof(List), typeof(string[]), null)]
+ public class StringListToArrayAdapter : IAdapter
+ {
+ public object Convert(object valueIn, AdapterOptions options)
+ {
+
+ if (valueIn == null)
+ {
+ return new string[0];
+ }
+
+ return ((List)valueIn).ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityWeld/Binding/DropdownBinding.cs b/UnityWeld/Binding/DropdownBinding.cs
index 264a7c5..521e108 100644
--- a/UnityWeld/Binding/DropdownBinding.cs
+++ b/UnityWeld/Binding/DropdownBinding.cs
@@ -14,12 +14,14 @@ public class DropdownBinding : AbstractMemberBinding
///
/// Name of the property in the view model to bind for the current selection.
///
- public string viewModelSelectionPropertyName;
+ [SerializeField]
+ private string viewModelSelectionPropertyName;
///
/// Name of the property in the view model to bind for the list of options.
///
- public string viewModelOptionsPropertyName;
+ [SerializeField]
+ private string viewModelOptionsPropertyName;
///
/// The name of the property to assign an exception to when adapter/validation fails.
@@ -57,7 +59,14 @@ public class DropdownBinding : AbstractMemberBinding
/// Adapter for converting the options list in the view model
/// to the correct format to display in the UI.
///
- public string optionsAdapter;
+ [SerializeField]
+ public string optionsViewAdapterTypeName;
+
+ ///
+ /// Option data to use for the options adapter
+ ///
+ [SerializeField]
+ public AdapterOptions optionsViewAdapterOptions;
///
/// Cached drop down component.
@@ -68,8 +77,8 @@ public override void Connect()
{
dropdown = GetComponent();
- var selectionPropertyEndPoint = MakeViewModelEndPoint(viewModelSelectionPropertyName, selectionUIToViewModelAdapter, null);
-
+ var selectionPropertyEndPoint = MakeViewModelEndPoint(ViewModelSelectionPropertyName, selectionUIToViewModelAdapter, null);
+
var selectionPropertySync = new PropertySync(
// Source
selectionPropertyEndPoint,
@@ -101,20 +110,20 @@ public override void Connect()
"onValueChanged",
() =>
{
- selectedOption = Options[dropdown.value]; // Copy value back from dropdown.
+ selectedOption = Options.Length > 0 ? Options[dropdown.value] : null; // Copy value back from dropdown.
selectionPropertySync.SyncFromDest();
}
);
var optionsPropertySync = new PropertySync(
// Source
- MakeViewModelEndPoint(viewModelOptionsPropertyName, null, null),
+ MakeViewModelEndPoint(ViewModelOptionsPropertyName, null, null),
// Dest
new PropertyEndPoint(
this,
"Options",
- CreateAdapter(optionsAdapter),
+ CreateAdapter(optionsViewAdapterTypeName),
null,
"view",
this
@@ -201,6 +210,24 @@ public string SelectedOption
}
}
+ public string ViewModelOptionsPropertyName
+ {
+ get { return viewModelOptionsPropertyName; }
+ set
+ {
+ viewModelOptionsPropertyName = value;
+ }
+ }
+
+ public string ViewModelSelectionPropertyName
+ {
+ get { return viewModelSelectionPropertyName; }
+ set
+ {
+ viewModelSelectionPropertyName = value;
+ }
+ }
+
///
/// Update the options.
///
@@ -209,6 +236,8 @@ private void UpdateOptions()
dropdown.options = options
.Select(option => new Dropdown.OptionData(option))
.ToList();
+
+ UpdateSelectedOption();
}
///
diff --git a/UnityWeld_Editor/DropdownBindingEditor.cs b/UnityWeld_Editor/DropdownBindingEditor.cs
new file mode 100644
index 0000000..0e0738a
--- /dev/null
+++ b/UnityWeld_Editor/DropdownBindingEditor.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEditor;
+using UnityEditor.AnimatedValues;
+using UnityEngine;
+using UnityWeld.Binding;
+using UnityWeld.Binding.Internal;
+
+namespace UnityWeld_Editor
+{
+ [CustomEditor(typeof(DropdownBinding))]
+ public class DropdownBindingEditor : BaseBindingEditor
+ {
+ private DropdownBinding targetScript;
+
+ private readonly bool viewPropertyPrefabModified;
+ private AnimBool optionsAdapterOptionsFade;
+
+ private void OnEnable()
+ {
+ // Initialise reference to target script
+ targetScript = (DropdownBinding)target;
+
+ Type adapterType;
+
+ optionsAdapterOptionsFade = new AnimBool(
+ ShouldShowAdapterOptions(targetScript.optionsViewAdapterTypeName, out adapterType)
+ );
+
+ optionsAdapterOptionsFade.valueChanged.AddListener(Repaint);
+ }
+
+ private void OnDisable()
+ {
+ optionsAdapterOptionsFade.valueChanged.RemoveListener(Repaint);
+ }
+
+ public override void OnInspectorGUI()
+ {
+ UpdatePrefabModifiedProperties();
+
+ var defaultLabelStyle = EditorStyles.label.fontStyle;
+ EditorStyles.label.fontStyle = viewPropertyPrefabModified
+ ? FontStyle.Bold
+ : defaultLabelStyle;
+
+ ShowViewModelPropertyMenu(
+ new GUIContent(
+ "Options: View-model property",
+ "Property on the view-model to bind Options to."
+ ),
+ TypeResolver.FindBindableProperties(targetScript),
+ updatedValue => targetScript.ViewModelOptionsPropertyName = updatedValue,
+ targetScript.ViewModelOptionsPropertyName,
+ property => property.PropertyType == typeof(string[]) || property.PropertyType == typeof(System.Collections.Generic.List)
+ );
+
+ Type viewPropertyType = typeof(string[]);
+
+ var viewAdapterTypeNames = GetAdapterTypeNames(
+ type =>
+ {
+ return viewPropertyType == null ||
+ TypeResolver.FindAdapterAttribute(type).OutputType == viewPropertyType;
+ });
+
+ var guiPreviouslyEnabled = GUI.enabled;
+
+ ShowAdapterMenu(
+ new GUIContent(
+ "View adapter",
+ "Adapter that converts values sent from the view-model to the view."
+ ),
+ viewAdapterTypeNames,
+ targetScript.optionsViewAdapterTypeName,
+ newValue =>
+ {
+ // Get rid of old adapter options if we changed the type of the adapter.
+ if (newValue != targetScript.optionsViewAdapterTypeName)
+ {
+ Undo.RecordObject(targetScript, "Set view adapter options");
+ targetScript.optionsViewAdapterTypeName = null;
+ }
+
+ UpdateProperty(
+ updatedValue => targetScript.optionsViewAdapterTypeName = updatedValue,
+ targetScript.optionsViewAdapterTypeName,
+ newValue,
+ "Set view adapter"
+ );
+ }
+ );
+
+ Type adapterType;
+ optionsAdapterOptionsFade.target = ShouldShowAdapterOptions(
+ targetScript.optionsViewAdapterTypeName,
+ out adapterType
+ );
+
+ ShowAdapterOptionsMenu(
+ "View adapter options",
+ adapterType,
+ options => targetScript.optionsViewAdapterOptions = options,
+ targetScript.optionsViewAdapterOptions,
+ optionsAdapterOptionsFade.faded
+ );
+
+
+
+ ShowViewModelPropertyMenu(
+ new GUIContent(
+ "Selected Item : View-model property",
+ "Property on the view-model to bind the selected item to."
+ ),
+ TypeResolver.FindBindableProperties(targetScript),
+ updatedValue => targetScript.ViewModelSelectionPropertyName = updatedValue,
+ targetScript.ViewModelSelectionPropertyName,
+ property => property.PropertyType == typeof(string)
+ );
+
+ GUI.enabled = guiPreviouslyEnabled;
+
+ EditorStyles.label.fontStyle = defaultLabelStyle;
+ }
+
+ ///
+ /// Check whether each of the properties on the object have been changed
+ /// from the value in the prefab.
+ ///
+ private void UpdatePrefabModifiedProperties()
+ {
+ var property = serializedObject.GetIterator();
+ // Need to call Next(true) to get the first child. Once we have it, Next(false)
+ // will iterate through the properties.
+ property.Next(true);
+ do
+ {
+ switch (property.name)
+ {
+
+ default:
+ //Debug.Log(property.name);
+ break;
+ }
+ }
+ while (property.Next(false));
+ }
+ }
+}
\ No newline at end of file