Exemplo n.º 1
0
        private bool TryExecuteCommand(VueBindingDescription binding, string value)
        {
            PropertyInfo propertyInfo = _dotnetViewModel.GetType().GetProperty(binding.PropertyName);

            if ((propertyInfo != null) && (propertyInfo.PropertyType == typeof(ICommand)))
            {
                ICommand command = propertyInfo.GetValue(_dotnetViewModel, null) as ICommand;
                command.Execute(value);
                return(true);
            }
            return(false);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets a value from a property of the ViewModel.
        /// </summary>
        /// <param name="binding">The description of the property binding.</param>
        /// <param name="propertyValue">Value of the property.</param>
        /// <returns>Returns true if the value could be retrieved successfully, otherwise false.</returns>
        private bool TryGetFromViewmodel(VueBindingDescription binding, out object propertyValue)
        {
            PropertyInfo propertyInfo = _dotnetViewModel.GetType().GetProperty(binding.PropertyName);

            if ((propertyInfo != null) && (propertyInfo.CanRead))
            {
                propertyValue = propertyInfo.GetValue(_dotnetViewModel, null);
                return(true);
            }
            propertyValue = null;
            return(false);
        }
Exemplo n.º 3
0
        internal bool TryFormatForView(VueBindingDescription binding, object value, out string formattedValue)
        {
            PropertyInfo propertyInfo = _dotnetViewModel.GetType().GetProperty(binding.PropertyName);

            if (propertyInfo != null)
            {
                Type propertyType = propertyInfo.PropertyType;
                if (value == null)
                {
                    formattedValue = "null";
                    return(true);
                }
                else if (propertyType == typeof(string))
                {
                    formattedValue = "'" + WebviewUtils.EscapeJavaScriptString(value.ToString()) + "'";
                    return(true);
                }
                else if (typeof(IEnumerable <string>).IsAssignableFrom(propertyType))
                {
                    IEnumerable <string> valueList = (IEnumerable <string>)value;
                    formattedValue = string.Join(
                        ",", valueList.Select(v => "'" + WebviewUtils.EscapeJavaScriptString(v) + "'"));
                    formattedValue = "[" + formattedValue + "]";
                    return(true);
                }
                else if (propertyType == typeof(bool))
                {
                    formattedValue = value.ToString().ToLowerInvariant();
                    return(true);
                }
                else if (propertyType == typeof(int))
                {
                    formattedValue = value.ToString();
                    return(true);
                }
                else if (propertyType == typeof(SecureString))
                {
                    // HTML doesn't know the concept of a SecureString, so this is the moment we have to switch.
                    string unprotectedValue = SecureStringExtensions.SecureStringToString((SecureString)value);
                    formattedValue = "'" + WebviewUtils.EscapeJavaScriptString(unprotectedValue) + "'";
                    return(true);
                }
            }
            formattedValue = null;
            return(false);
        }
Exemplo n.º 4
0
        private bool TrySetToViewmodel(VueBindingDescription binding, string formattedValue)
        {
            if (string.IsNullOrEmpty(binding?.PropertyName))
            {
                return(false);
            }

            if (TryParseFromView(binding, formattedValue, out object value))
            {
                PropertyInfo propertyInfo = _dotnetViewModel.GetType().GetProperty(binding.PropertyName);
                if ((propertyInfo != null) && (propertyInfo.CanWrite))
                {
                    propertyInfo.SetValue(_dotnetViewModel, value);
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 5
0
 /// <summary>
 /// Sets a value to the Vue-model in the View.
 /// </summary>
 /// <param name="binding">The description of the property binding.</param>
 /// <param name="value">New value of the property.</param>
 /// <returns>Returns true if the value could be set successfully, otherwise false.</returns>
 private bool TrySetToView(VueBindingDescription binding, object value)
 {
     if (TryFormatForView(binding, value, out string formattedValue))
     {
         try
         {
             string script = string.Format(
                 "var newValue = {2}; if ({0}.{1} != newValue) {0}.{1} = newValue;", "vm", binding.PropertyName, formattedValue);
             _htmlView.ExecuteJavaScript(script);
             return(true);
         }
         catch (Exception)
         {
             // This will return false
         }
     }
     return(false);
 }
Exemplo n.º 6
0
        internal bool TryParseFromView(VueBindingDescription binding, string formattedValue, out object value)
        {
            PropertyInfo propertyInfo = _dotnetViewModel.GetType().GetProperty(binding.PropertyName);

            if (propertyInfo != null)
            {
                try
                {
                    Type propertyType = propertyInfo.PropertyType;
                    if (string.Equals("null", formattedValue, StringComparison.InvariantCultureIgnoreCase))
                    {
                        value = null;
                        return(true);
                    }
                    else if (propertyType == typeof(string))
                    {
                        value = formattedValue;
                        return(true);
                    }
                    else if (propertyType == typeof(bool))
                    {
                        value = bool.Parse(formattedValue);
                        return(true);
                    }
                    else if (propertyType == typeof(int))
                    {
                        value = int.Parse(formattedValue);
                        return(true);
                    }
                    else if (propertyType == typeof(SecureString))
                    {
                        value = SecureStringExtensions.StringToSecureString(formattedValue);
                        return(true);
                    }
                }
                catch (Exception)
                {
                    // This will return false
                }
            }
            value = null;
            return(false);
        }
Exemplo n.º 7
0
        /// <summary>
        /// This method is called when the viewmodel modified a property and raised an
        /// INotifyPropertyChanged event.
        /// </summary>
        /// <param name="sender">Sender of the event.</param>
        /// <param name="e">Event arguments.</param>
        private void ViewmodelPropertyChangedHandler(object sender, PropertyChangedEventArgs e)
        {
            if (!IsListening)
            {
                return;
            }

            VueBindingDescription binding = _bindingDescriptions.FindByPropertyName(e.PropertyName);

            if (binding == null)
            {
                return;
            }

            bool isSuppressedEvent = string.Equals(binding.PropertyName, _suppressedViewmodelPropertyChangedEvent);

            if (isSuppressedEvent)
            {
                return;
            }

            switch (binding.BindingMode)
            {
            case VueBindingMode.TwoWay:
            case VueBindingMode.OneWayToView:
                if (TryGetFromViewmodel(binding, out object propertyValue))
                {
                    TrySetToView(binding, propertyValue);
                }
                break;

            case VueBindingMode.OneWayToViewmodel:
                break;

            case VueBindingMode.Command:
                break;     // Should never happen

            default:
                throw new ArgumentOutOfRangeException(nameof(binding.BindingMode));
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// This method is called by the JavaScript, triggered by the Vue model.
        /// </summary>
        /// <param name="sender">The sender of the event.</param>
        /// <param name="uri">The navigation uri, which should be filtered for binding commands.</param>
        private void NavigatingEventHandler(object sender, string uri)
        {
            if (!IsListening || !IsVueBindingUri(uri))
            {
                return;
            }

            if (uri.Contains("vueLoaded"))
            {
                ViewLoadedEvent?.Invoke(this, new EventArgs());
                return;
            }

            string queryPart = GetUriQueryPart(uri);
            NameValueCollection queryArguments = HttpUtility.ParseQueryString(queryPart);
            string propertyName = queryArguments.Get("name");
            string value        = queryArguments.Get("value");

            VueBindingDescription binding = _bindingDescriptions.FindByPropertyName(propertyName);

            if (binding != null)
            {
                switch (binding.BindingMode)
                {
                case VueBindingMode.TwoWay:
                case VueBindingMode.OneWayToViewmodel:
                    try
                    {
                        // We are inside a changed event from the view, so we do not want to
                        // handle events from the viewmodel to update the view again, because
                        // this could lead to circles.
                        _suppressedViewmodelPropertyChangedEvent = binding.PropertyName;
                        TrySetToViewmodel(binding, value);
                    }
                    finally
                    {
                        _suppressedViewmodelPropertyChangedEvent = null;
                    }
                    break;

                case VueBindingMode.Command:
                    TryExecuteCommand(binding, value);
                    break;

                case VueBindingMode.OneWayToView:
                    break;     // Should never happen

                default:
                    throw new ArgumentOutOfRangeException(nameof(binding.BindingMode));
                }
            }
            else
            {
                // Collect individually named arguments
                var arguments = new KeyValueList <string, string>(StringComparer.InvariantCultureIgnoreCase);
                foreach (string item in queryArguments)
                {
                    if (!string.Equals("name", item, StringComparison.InvariantCultureIgnoreCase) &&
                        !string.Equals("value", item, StringComparison.InvariantCultureIgnoreCase))
                    {
                        arguments[item] = queryArguments[item];
                    }
                }
                UnhandledViewBindingEvent?.Invoke(this, new VueBindingUnhandledViewBindingEventArgs(propertyName, value, arguments));
            }
        }