/// <summary> /// Configures the container using the provided component registrations. /// </summary> /// <param name="registrations">The component registrations.</param> public virtual void Register(IEnumerable <IComponentRegistration> registrations) { foreach (var registration in registrations) { var key = registration.GetType(); Delegate handler; if (handlers.TryGetValue(key, out handler)) { handler.DynamicInvoke(registration); } else { var exception = new CaliburnException( string.Format( "{0} cannot handle registrations of type {1}. Please add an appropriate registration handler.", GetType().FullName, key.FullName ) ); Log.Error(exception); throw exception; } } }
/// <summary> /// Determines the parameters that a method should be invoked with. /// </summary> /// <param name="message">The message to determine the parameters for.</param> /// <param name="requiredParameters">The requirements for method binding.</param> /// <param name="handlingNode">The handling node.</param> /// <param name="context">The context.</param> /// <returns>The actual parameter values.</returns> public virtual object[] DetermineParameters(IRoutedMessage message, IList <RequiredParameter> requiredParameters, IInteractionNode handlingNode, object context) { if (requiredParameters == null || requiredParameters.Count == 0) { return new object[] {} } ; var providedValues = message.Parameters.Select(x => x.Value).ToArray(); if (requiredParameters.Count <= providedValues.Length) { return(CoerceValues(requiredParameters, providedValues, message.Source, context)); } if (providedValues.Length == 0) { return(LocateAndCoerceValues(requiredParameters, message.Source, handlingNode, context)); } var exception = new CaliburnException( string.Format( "Parameter count mismatch. {0} parameters were provided but {1} are required for {2}.", providedValues.Length, requiredParameters.Count, message ) ); Log.Error(exception); throw exception; }
/// <summary> /// Gets the data context of the depdendency object. /// </summary> /// <param name="dependencyObject">The dependency object.</param> /// <returns>The data context value.</returns> public static object GetDataContext(this DependencyObject dependencyObject) { var fe = dependencyObject as FrameworkElement; if (fe != null) { return(fe.DataContext); } #if !SILVERLIGHT var fce = dependencyObject as FrameworkContentElement; if (fce != null) { return(fce.DataContext); } #endif var exception = new CaliburnException( string.Format( "Instance {0} must be a FrameworkElement or FrameworkContentElement in order to get its DataContext property.", dependencyObject.GetType().Name ) ); Log.Error(exception); throw exception; }
/// <summary> /// Wires the trigger into the interactin hierarchy. /// </summary> /// <param name="node">The node.</param> public override void Attach(IInteractionNode node) { InputGesture gesture; if (Key != Key.None) { gesture = new UnrestrictedKeyGesture(Key, Modifiers); } else { gesture = new MouseGesture(MouseAction, Modifiers); } var uiElement = node.UIElement as UIElement; if (uiElement == null) { var ex = new CaliburnException( string.Format( "You cannot use a GestureMessageTrigger with an instance of {0}. The source element must inherit from UIElement.", node.UIElement.GetType().FullName ) ); Log.Error(ex); throw ex; } FindOrCreateLookup(uiElement, gesture) .AddTrigger(this); base.Attach(node); }
/// <summary> /// Initializes the backing store. /// </summary> /// <param name="stateName">Name of the state.</param> /// <returns></returns> public virtual bool Initialize(string stateName) { if (string.IsNullOrEmpty(stateName)) { var ex = new CaliburnException("State name is null or empty."); Log.Error(ex); throw ex; } this.stateName = stateName; return(LoadState()); }
/// <summary> /// Initializes the backing store. /// </summary> /// <param name="stateName">Name of the state.</param> /// <returns></returns> public virtual bool Initialize(string stateName) { if(string.IsNullOrEmpty(stateName)) { var ex = new CaliburnException("State name is null or empty."); Log.Error(ex); throw ex; } _stateName = stateName; return LoadState(); }
public void MarkAsBusy(object sourceViewModel, object busyViewModel) { sourceViewModel = sourceViewModel ?? _defaultKey; if (_loaders.ContainsKey(sourceViewModel)) { BusyInfo info = _loaders[sourceViewModel]; info.BusyViewModel = busyViewModel; UpdateLoader(info); } else { UIElement busyIndicator = TryFindBusyIndicator(sourceViewModel); if (busyIndicator == null) { #if WP7 var ex = new CaliburnException("No busy indicator with name '" + BusyIndicatorName + "' was found in the UI hierarchy."); Log.Error(ex); throw ex; #else var notifier = busyViewModel as IActivate; if (notifier == null) return; notifier.Activated += (o, e) => { if (e.WasInitialized) { var info = new BusyInfo {BusyViewModel = busyViewModel}; _loaders[sourceViewModel] = info; UpdateLoader(info); } }; Log.Warn("No busy indicator with name '" + BusyIndicatorName + "' was found in the UI hierarchy. Using modal."); _windowManager.ShowDialog(busyViewModel, null); #endif } else { var info = new BusyInfo {BusyIndicator = busyIndicator, BusyViewModel = busyViewModel}; _loaders[sourceViewModel] = info; ToggleBusyIndicator(info, true); UpdateLoader(info); } } }
/// <summary> /// Processes the specified message. /// </summary> /// <param name="message">The message.</param> /// <param name="context">An object that provides additional context for message processing.</param> public void Process(IRoutedMessage message, object context) { if (message != this) { var ex = new CaliburnException("The handler cannot process the message."); Log.Error(ex); throw ex; } CreateActionMessage(); action.Execute(actionMessage, Source, context); Log.Info("Processed {0} on command {1}.", actionMessage, Command); }
/// <summary> /// Processes the specified message. /// </summary> /// <param name="message">The message.</param> /// <param name="context">An object that provides additional context for message processing.</param> public void Process(IRoutedMessage message, object context) { var actionMessage = message as ActionMessage; if (actionMessage != null) { FindActionHandler(actionMessage).Execute(actionMessage, node, context); Log.Info("Processed message {0}.", actionMessage); } else { var ex = new CaliburnException("The handler cannot process this message."); Log.Error(ex); throw ex; } }
/// <summary> /// Parses the specified trigger text. /// </summary> /// <param name="target">The targeted ui element.</param> /// <param name="triggerText">The trigger text.</param> /// <returns></returns> public IMessageTrigger Parse(DependencyObject target, string triggerText) { var keyValues = triggerText.Split(new[] { ",", ":" }, StringSplitOptions.RemoveEmptyEntries); var trigger = new GestureMessageTrigger(); for (int i = 0; i < keyValues.Length; i += 2) { switch (keyValues[i].Trim()) { case "Key": #if !SILVERLIGHT trigger.Key = (Key) new KeyConverter() .ConvertFrom(keyValues[i + 1].Trim()); #else trigger.Key = (Key)Enum.Parse(typeof(Key), keyValues[i + 1].Trim(), true); #endif break; case "Modifiers": #if !SILVERLIGHT trigger.Modifiers = (ModifierKeys) new ModifierKeysConverter() .ConvertFrom(keyValues[i + 1].Trim()); #else trigger.Modifiers = (ModifierKeys)Enum.Parse(typeof(ModifierKeys), keyValues[i + 1].Trim(), true); #endif break; case "MouseAction": #if !SILVERLIGHT trigger.MouseAction = (MouseAction) new MouseActionConverter() .ConvertFrom(keyValues[i + 1].Trim()); #else trigger.MouseAction = (MouseAction)Enum.Parse(typeof(MouseAction), keyValues[i + 1].Trim(), true); #endif break; default: var exception = new CaliburnException(keyValues[i] + " was not recognized by the gesture trigger parser."); Log.Error(exception); throw exception; } } return(trigger); }
/// <summary> /// Updates the availability of the trigger. /// </summary> /// <param name="trigger">The trigger.</param> public void UpdateAvailability(IMessageTrigger trigger) { if (trigger.Message != this) { var ex = new CaliburnException("The handler cannot update availability for this trigger."); Log.Error(ex); throw ex; } if (Command != null) { CreateActionMessage(); bool isAvailable = action.ShouldTriggerBeAvailable(actionMessage, Source); trigger.UpdateAvailabilty(isAvailable); TryUpdateParentAvailability(isAvailable); } }
/// <summary> /// Updates the availability of the trigger. /// </summary> /// <param name="trigger">The trigger.</param> public void UpdateAvailability(IMessageTrigger trigger) { var actionMessage = trigger.Message as ActionMessage; if (actionMessage == null) { var ex = new CaliburnException("The handler cannot update availability for this trigger."); Log.Error(ex); throw ex; } Log.Info("Requesting update avaiability for {0}.", actionMessage); var action = FindActionHandler(actionMessage); bool isAvailable = action.ShouldTriggerBeAvailable(actionMessage, node); trigger.UpdateAvailabilty(isAvailable); }
/// <summary> /// Parses the specified trigger text. /// </summary> /// <param name="target">The targeted ui element.</param> /// <param name="triggerText">The trigger text.</param> /// <returns></returns> public IMessageTrigger Parse(DependencyObject target, string triggerText) { var keyValues = triggerText.Split(new[] {",", ":"}, StringSplitOptions.RemoveEmptyEntries); var trigger = new GestureMessageTrigger(); for(int i = 0; i < keyValues.Length; i += 2) { switch(keyValues[i].Trim()) { case "Key": #if !SILVERLIGHT trigger.Key = (Key)new KeyConverter() .ConvertFrom(keyValues[i + 1].Trim()); #else trigger.Key = (Key)Enum.Parse(typeof(Key), keyValues[i + 1].Trim(), true); #endif break; case "Modifiers": #if !SILVERLIGHT trigger.Modifiers = (ModifierKeys)new ModifierKeysConverter() .ConvertFrom(keyValues[i + 1].Trim()); #else trigger.Modifiers = (ModifierKeys)Enum.Parse(typeof(ModifierKeys), keyValues[i + 1].Trim(), true); #endif break; case "MouseAction": #if !SILVERLIGHT trigger.MouseAction = (MouseAction)new MouseActionConverter() .ConvertFrom(keyValues[i + 1].Trim()); #else trigger.MouseAction = (MouseAction)Enum.Parse(typeof(MouseAction), keyValues[i + 1].Trim(), true); #endif break; default: var exception = new CaliburnException(keyValues[i] + " was not recognized by the gesture trigger parser."); Log.Error(exception); throw exception; } } return trigger; }
/// <summary> /// Wires the trigger into the interaction hierarchy. /// </summary> /// <param name="node">The node.</param> public override void Attach(IInteractionNode node) { var commandProperty = node.UIElement.GetType().GetProperty("Command"); if(commandProperty == null) { var ex = new CaliburnException( string.Format( "You cannot use a CommandMessageTrigger with an instance of {0}. The source element should be an ICommandSource.", node.UIElement.GetType().FullName ) ); Log.Error(ex); throw ex; } commandProperty.SetValue(node.UIElement, this, null); base.Attach(node); }
/// <summary> /// Wires the trigger into the interaction hierarchy. /// </summary> /// <param name="node">The node.</param> public override void Attach(IInteractionNode node) { var commandProperty = node.UIElement.GetType().GetProperty("Command"); if (commandProperty == null) { var ex = new CaliburnException( string.Format( "You cannot use a CommandMessageTrigger with an instance of {0}. The source element should be an ICommandSource.", node.UIElement.GetType().FullName ) ); Log.Error(ex); throw ex; } commandProperty.SetValue(node.UIElement, this, null); base.Attach(node); }
/// <summary> /// Locates the routed event. /// </summary> /// <param name="target">The target.</param> /// <param name="triggerText">The trigger text.</param> /// <returns></returns> protected virtual RoutedEvent GetRoutedEvent(DependencyObject target, string triggerText) { var eventOwner = target.GetType(); if (triggerText.Contains(".")) { var ownerTypeName = triggerText.Substring(0, triggerText.LastIndexOf(".")); triggerText = triggerText.Substring(ownerTypeName.Length + 1); var types = GetSearchableAssemblies().SelectMany(a => a.GetExportedTypes()) .Where(x => DependencyObjectType.IsAssignableFrom(x) || (x.IsAbstract && x.IsSealed)); eventOwner = types.Where(t => t.FullName.Equals(ownerTypeName)).FirstOrDefault() ?? types.Where(t => t.Name.Equals(ownerTypeName)).FirstOrDefault(); if (eventOwner == null) { var exception = new CaliburnException("Type " + ownerTypeName + " not found."); Log.Error(exception); throw exception; } } var fieldEventProp = eventOwner.GetField(triggerText + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); if (fieldEventProp == null) { var exception = new CaliburnException(triggerText + " event was not found on type " + eventOwner.Name + "."); Log.Error(exception); throw exception; } if (!typeof(RoutedEvent).IsAssignableFrom(fieldEventProp.FieldType)) { var exception = new CaliburnException(triggerText + " event was not found on type " + eventOwner.Name + "."); Log.Error(exception); throw exception; } return((RoutedEvent)fieldEventProp.GetValue(null)); }
/// <summary> /// Locates the routed event. /// </summary> /// <param name="target">The target.</param> /// <param name="triggerText">The trigger text.</param> /// <returns></returns> protected virtual RoutedEvent GetRoutedEvent(DependencyObject target, string triggerText) { var eventOwner = target.GetType(); if (triggerText.Contains(".")) { var ownerTypeName = triggerText.Substring(0, triggerText.LastIndexOf(".")); triggerText = triggerText.Substring(ownerTypeName.Length + 1); var types = GetSearchableAssemblies().SelectMany(a => a.GetExportedTypes()) .Where(x => _dependencyObjectType.IsAssignableFrom(x) || (x.IsAbstract && x.IsSealed)); eventOwner = types.Where(t => t.FullName.Equals(ownerTypeName)).FirstOrDefault() ?? types.Where(t => t.Name.Equals(ownerTypeName)).FirstOrDefault(); if (eventOwner == null) { var exception = new CaliburnException("Type " + ownerTypeName + " not found."); Log.Error(exception); throw exception; } } var fieldEventProp = eventOwner.GetField(triggerText + "Event", BindingFlags.Static | BindingFlags.Public); if (fieldEventProp == null) { var exception = new CaliburnException(triggerText + " event was not found on type " + eventOwner.Name + "."); Log.Error(exception); throw exception; } if (!typeof(RoutedEvent).IsAssignableFrom(fieldEventProp.FieldType)) { var exception = new CaliburnException(triggerText + " event was not found on type " + eventOwner.Name + "."); Log.Error(exception); throw exception; } return (RoutedEvent)fieldEventProp.GetValue(null); }
/// <summary> /// Wires the trigger into the interaction hierarchy. /// </summary> /// <param name="node">The node.</param> public override void Attach(IInteractionNode node) { var element = node.UIElement as UIElement; if(element != null) element.AddHandler(RoutedEvent, new RoutedEventHandler(Event_Occurred)); else { var ex = new CaliburnException( string.Format( "You cannot use a RoutedEventMessageTrigger with an instance of {0}. The source element must inherit from UIElement.", node.UIElement.GetType().FullName ) ); Log.Error(ex); throw ex; } base.Attach(node); }
/// <summary> /// Finds an element by name or fails. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="element">The element.</param> /// <param name="name">The name.</param> /// <param name="shouldFail">Indicates whether an exception should be throw if the named item is not found.</param> /// <returns>The found element.</returns> public static T FindNameExhaustive <T>(this DependencyObject element, string name, bool shouldFail) where T : class { T found = null; if (!string.IsNullOrEmpty(name)) { found = (name == "$this" ? element as T : element.FindName(name) as T) ?? element.GetResource <T>(name); } if (found == null && shouldFail) { var exception = new CaliburnException( string.Format("Could not locate {0} with name {1}.", typeof(T).Name, name) ); Log.Error(exception); throw exception; } return(found); }
/// <summary> /// Wires the trigger into the interaction hierarchy. /// </summary> /// <param name="node">The node.</param> public override void Attach(IInteractionNode node) { var element = node.UIElement as UIElement; if (element != null) { element.AddHandler(RoutedEvent, new RoutedEventHandler(Event_Occurred)); } else { var ex = new CaliburnException( string.Format( "You cannot use a RoutedEventMessageTrigger with an instance of {0}. The source element must inherit from UIElement.", node.UIElement.GetType().FullName ) ); Log.Error(ex); throw ex; } base.Attach(node); }
private IRoutedMessageHandler FindHandlerOrFail(IRoutedMessage message, bool shouldFail) { IInteractionNode currentNode = this; while (currentNode != null && !currentNode.Handles(message)) { currentNode = currentNode.FindParent(); } if (currentNode == null) { foreach (var handler in message.GetDefaultHandlers(this)) { if (handler.Handles(message)) { RegisterHandler(handler); return(handler); } } var info = string.Format( "There was no handler found for the message {0}.", message ); if (shouldFail) { var exception = new CaliburnException(info); Log.Error(exception); throw exception; } Log.Info(info); } return(currentNode != null ? currentNode.MessageHandler : null); }
/// <summary> /// Determines the overload or fail. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> public IAction DetermineOverloadOrFail(ActionMessage message) { foreach (var overload in overloads) { if (overload.Matches(message)) { return(overload); } } if (message.Parameters.Count > 0) { var ex = new CaliburnException( string.Format( "Could not find overload for {0}({1}).", message.MethodName, message.Parameters .Select(x => x.Value == null ? "null" : x.Value.GetType().Name) .Aggregate((a, c) => a + ", " + c) ) ); Log.Error(ex); throw ex; } var ex2 = new CaliburnException( string.Format( "Could not find overload for {0}().", message.MethodName ) ); Log.Error(ex2); throw ex2; }
/// <summary> /// Updates the availability of the trigger. /// </summary> /// <param name="trigger">The trigger.</param> public void UpdateAvailability(IMessageTrigger trigger) { if(trigger.Message != this) { var ex = new CaliburnException("The handler cannot update availability for this trigger."); Log.Error(ex); throw ex; } if (Command != null) { CreateActionMessage(); bool isAvailable = action.ShouldTriggerBeAvailable(actionMessage, Source); trigger.UpdateAvailabilty(isAvailable); TryUpdateParentAvailability(isAvailable); } }
/// <summary> /// Parses the specified message text. /// </summary> /// <param name="target">The target.</param> /// <param name="messageText">The message text.</param> /// <returns>The triggers parsed from the text.</returns> protected virtual IMessageTrigger ParseMessage(string messageText, DependencyObject target) { var triggerPlusMessage = messageText.Split('='); string messageDetail = triggerPlusMessage.Last() .Replace("[", string.Empty) .Replace("]", string.Empty) .Trim(); IRoutedMessage message = null; foreach (var keyValuePair in _messageParsers) { if (messageDetail.StartsWith(keyValuePair.Key, StringComparison.CurrentCultureIgnoreCase)) { message = keyValuePair.Value .Parse(target, messageDetail.Remove(0, keyValuePair.Key.Length).Trim()); break; } } if (message == null) { message = _messageParsers[_defaultMessageParserKey] .Parse(target, messageDetail); Log.Info("Using default parser {0} for {1} on {2}.", _defaultMessageParserKey, messageText, target); } IMessageTrigger trigger = null; if (triggerPlusMessage.Length == 1) { var defaults = _conventionManager.FindElementConventionOrFail(target); trigger = defaults.CreateTrigger(); Log.Info("Using default trigger {0} for {1} on {2}.", trigger, messageText, target); } else { var triggerDetail = triggerPlusMessage[0] .Replace("[", string.Empty) .Replace("]", string.Empty) .Trim(); foreach (var keyValuePair in _triggerParsers) { if (triggerDetail.StartsWith(keyValuePair.Key, StringComparison.CurrentCultureIgnoreCase)) { trigger = keyValuePair.Value .Parse(target, triggerDetail.Remove(0, keyValuePair.Key.Length).Trim()); break; } } } if (trigger == null) { var exception = new CaliburnException("Could not determine trigger type."); Log.Error(exception); throw exception; } trigger.Message = message; return trigger; }
/// <summary> /// Wires the trigger into the interactin hierarchy. /// </summary> /// <param name="node">The node.</param> public override void Attach(IInteractionNode node) { InputGesture gesture; if(Key != Key.None) gesture = new UnrestrictedKeyGesture(Key, Modifiers); else gesture = new MouseGesture(MouseAction, Modifiers); var uiElement = node.UIElement as UIElement; if(uiElement == null) { var ex = new CaliburnException( string.Format( "You cannot use a GestureMessageTrigger with an instance of {0}. The source element must inherit from UIElement.", node.UIElement.GetType().FullName ) ); Log.Error(ex); throw ex; } FindOrCreateLookup(uiElement, gesture) .AddTrigger(this); base.Attach(node); }
/// <summary> /// Processes the specified message. /// </summary> /// <param name="message">The message.</param> /// <param name="context">An object that provides additional context for message processing.</param> public void Process(IRoutedMessage message, object context) { var actionMessage = message as ActionMessage; if (actionMessage != null) { FindActionHandler(actionMessage).Execute(actionMessage, _node, context); Log.Info("Processed message {0}.", actionMessage); } else { var ex = new CaliburnException("The handler cannot process this message."); Log.Error(ex); throw ex; } }
/// <summary> /// Updates the availability of the trigger. /// </summary> /// <param name="trigger">The trigger.</param> public void UpdateAvailability(IMessageTrigger trigger) { var actionMessage = trigger.Message as ActionMessage; if(actionMessage == null) { var ex = new CaliburnException("The handler cannot update availability for this trigger."); Log.Error(ex); throw ex; } Log.Info("Requesting update avaiability for {0}.", actionMessage); var action = FindActionHandler(actionMessage); bool isAvailable = action.ShouldTriggerBeAvailable(actionMessage, _node); trigger.UpdateAvailabilty(isAvailable); }
private IRoutedMessageHandler FindHandlerOrFail(IRoutedMessage message, bool shouldFail) { IInteractionNode currentNode = this; while(currentNode != null && !currentNode.Handles(message)) { currentNode = currentNode.FindParent(); } if(currentNode == null) { foreach(var handler in message.GetDefaultHandlers(this)) { if (handler.Handles(message)) { RegisterHandler(handler); return handler; } } var info = string.Format( "There was no handler found for the message {0}.", message ); if (shouldFail) { var exception = new CaliburnException(info); Log.Error(exception); throw exception; } Log.Info(info); } return currentNode != null ? currentNode.MessageHandler : null; }
/// <summary> /// Parses the specified message text. /// </summary> /// <param name="target">The target.</param> /// <param name="messageText">The message text.</param> /// <returns>The triggers parsed from the text.</returns> protected virtual IMessageTrigger ParseMessage(string messageText, DependencyObject target) { var triggerPlusMessage = messageText.Split('='); string messageDetail = triggerPlusMessage.Last() .Replace("[", string.Empty) .Replace("]", string.Empty) .Trim(); IRoutedMessage message = null; foreach (var keyValuePair in messageParsers) { if (messageDetail.StartsWith(keyValuePair.Key, StringComparison.CurrentCultureIgnoreCase)) { message = keyValuePair.Value .Parse(target, messageDetail.Remove(0, keyValuePair.Key.Length).Trim()); break; } } if (message == null) { message = messageParsers[defaultMessageParserKey] .Parse(target, messageDetail); Log.Info("Using default parser {0} for {1} on {2}.", defaultMessageParserKey, messageText, target); } IMessageTrigger trigger = null; if (triggerPlusMessage.Length == 1) { var defaults = conventionManager.FindElementConventionOrFail(target); trigger = defaults.CreateTrigger(); Log.Info("Using default trigger {0} for {1} on {2}.", trigger, messageText, target); } else { var triggerDetail = triggerPlusMessage[0] .Replace("[", string.Empty) .Replace("]", string.Empty) .Trim(); foreach (var keyValuePair in triggerParsers) { if (triggerDetail.StartsWith(keyValuePair.Key, StringComparison.CurrentCultureIgnoreCase)) { trigger = keyValuePair.Value .Parse(target, triggerDetail.Remove(0, keyValuePair.Key.Length).Trim()); break; } } } if (trigger == null) { var exception = new CaliburnException("Could not determine trigger type."); Log.Error(exception); throw exception; } trigger.Message = message; return(trigger); }