示例#1
0
        /// <summary>
        /// Modifies the source data before passing it to the target for display in the UI.
        /// </summary>
        /// <param name="value">The source data being passed to the target.</param>
        /// <param name="targetType">The <see cref="T:System.Type" /> of data expected by the target dependency property.</param>
        /// <param name="parameter">An optional parameter to be used in the converter logic.</param>
        /// <param name="culture">The culture of the conversion.</param>
        /// <returns>The value to be passed to the target dependency property.</returns>
        public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            CurrentCulture = culture;

            var returnValue = value;

            if (Link != null)
            {
#if NETFX_CORE
                var cultureToUse = culture.Name;
#else
                var cultureToUse = culture;
#endif

                // Linked converter is set, this is not the last in the chain
                // call the linked converter, i.e. the next in the chain
                returnValue = Link.Convert(returnValue, OverrideType ?? targetType, parameter, cultureToUse);
            }

            if (!IsConvertable <TConvert>(value))
            {
                Log.Warning("Cannot convert value of type '{0}', expected type '{1}', ignoring converter results",
                            ObjectToStringHelper.ToTypeString(returnValue), typeof(TConvert));

                return(ConverterHelper.UnsetValue);
            }

            returnValue = Convert((TConvert)returnValue, targetType, parameter);

            return(returnValue);
        }
示例#2
0
        /// <summary>
        /// Modifies the target data before passing it to the source object.
        /// </summary>
        /// <param name="value">The target data being passed to the source.</param>
        /// <param name="targetType">The <see cref="T:System.Type" /> of data expected by the source object.</param>
        /// <param name="parameter">An optional parameter to be used in the converter logic.</param>
        /// <param name="culture">The culture of the conversion.</param>
        /// <returns>The value to be passed to the source object.</returns>
        public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            CurrentCulture = culture;

            var returnValue = value;

            if (!IsConvertable <TConvertBack>(value))
            {
                Log.Warning("Cannot convert back value of type '{0}', expected type '{1}', ignoring converter results",
                            ObjectToStringHelper.ToTypeString(returnValue), typeof(TConvertBack));

                returnValue = ConverterHelper.UnsetValue;
            }

            // Call ConvertBack first because we are doing this in reverse order
            returnValue = ConvertBack((TConvertBack)returnValue, targetType, parameter);

            if (Link != null)
            {
#if NETFX_CORE
                var cultureToUse = culture.Name;
#else
                var cultureToUse = culture;
#endif

                returnValue = Link.ConvertBack(returnValue, BackOverrideType ?? targetType, parameter, cultureToUse);
            }

            return(returnValue);
        }
示例#3
0
        /// <summary>
        /// Unregisters the model of a view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <param name="model">The model.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="viewModel"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="model"/> is <c>null</c>.</exception>
        public void UnregisterModel(IViewModel viewModel, object model)
        {
            Argument.IsNotNull("viewModel", viewModel);
            Argument.IsNotNull("model", model);

            var viewModelTypeName = ObjectToStringHelper.ToTypeString(viewModel);
            var modelTypeName     = ObjectToStringHelper.ToTypeString(model);

            Log.Debug("Unregistering model '{0}' with view model '{1}' (id = '{2}')", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);

            var modelWasRemoved = false;

            lock (_viewModelModelsLock)
            {
                if (_viewModelModels.TryGetValue(viewModel.UniqueIdentifier, out var models))
                {
                    models.Remove(model);
                    modelWasRemoved = true;
                }
            }

            if (modelWasRemoved)
            {
                Log.Debug("Unregistered model '{0}' with view model '{1}' (id = '{2}')", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);
            }
            else
            {
                Log.Debug("Model '{0}' was not registered with view model '{1}' (id = '{2}') or has already been unregistered.", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);
            }
        }
示例#4
0
        /// <summary>
        /// Creates a new view model.
        /// </summary>
        /// <param name="viewModelType">Type of the view model that needs to be created.</param>
        /// <param name="dataContext">The data context of the view model.</param>
        /// <param name="tag">The preferred tag to use when resolving dependencies.</param>
        /// <returns>The newly created <see cref="IViewModel"/> or <c>null</c> if no view model could be created.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="viewModelType"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">The <paramref name="viewModelType"/> does not implement the <see cref="IViewModel"/> interface.</exception>
        public virtual IViewModel CreateViewModel(Type viewModelType, object dataContext, object tag = null)
        {
            Argument.IsNotNull("viewModelType", viewModelType);
            Argument.ImplementsInterface("viewModelType", viewModelType, typeof(IViewModel));

            IViewModel viewModel = null;

            // Only try to construct the view model when the injection object is not null, otherwise every
            // view model can be constructed with a nullable object. If a user wants a view model to be constructed
            // without any datacontext or injection, he/she should use an empty default constructor which will only
            // be used when injection is not possible
            if (dataContext != null)
            {
                viewModel = _typeFactory.CreateInstanceWithParametersAndAutoCompletionWithTag(viewModelType, tag, dataContext) as IViewModel;
                if (viewModel != null)
                {
                    Log.Debug("Constructed view model '{0}' using injection of data context '{1}'", viewModelType.FullName, ObjectToStringHelper.ToTypeString(dataContext));
                    return(viewModel);
                }
            }

            // Try to construct view model using dependency injection
            viewModel = _typeFactory.CreateInstanceWithTag(viewModelType, tag) as IViewModel;
            if (viewModel != null)
            {
                Log.Debug("Constructed view model '{0}' using dependency injection or empty constructor", viewModelType.FullName);
                return(viewModel);
            }

            Log.Debug("Could not construct view model '{0}' using injection of data context '{1}'",
                      viewModelType.FullName, ObjectToStringHelper.ToTypeString(dataContext));

            return(viewModel);
        }
示例#5
0
        /// <summary>
        /// Gets the view models of a model.
        /// </summary>
        /// <param name="model">The model to find the linked view models for.</param>
        /// <returns>An array containing all the view models.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="model"/> is <c>null</c>.</exception>
        public IViewModel[] GetViewModelsOfModel(object model)
        {
            Argument.IsNotNull("model", model);

            var modelType = ObjectToStringHelper.ToTypeString(model);

            Log.Debug("Getting all view models that are linked to model '{0}'", modelType);

            var viewModels = new List <IViewModel>();

            lock (_viewModelModelsLock)
            {
                foreach (var viewModelModel in _viewModelModels)
                {
                    var viewModelIdentifiers = (from m in viewModelModel.Value
                                                where ObjectHelper.AreEqualReferences(m, model)
                                                select viewModelModel.Key);

                    foreach (var viewModelIdentifier in viewModelIdentifiers)
                    {
                        var vm = GetViewModel(viewModelIdentifier);
                        if (vm != null)
                        {
                            viewModels.Add(vm);
                        }
                    }
                }
            }

            Log.Debug("Found '{0}' view models that are linked to model '{1}'", viewModels.Count, modelType);

            return(viewModels.ToArray());
        }
示例#6
0
        /// <summary>
        /// Initializes the created object after its construction.
        /// </summary>
        /// <param name="obj">The object to initialize.</param>
        private void InitializeAfterConstruction(object obj)
        {
            if (obj == null)
            {
                return;
            }

            string objectType = ObjectToStringHelper.ToTypeString(obj);

            Log.Debug("Initializing type '{0}' after construction", objectType);

            // TODO: Consider to cache for performance
            var dependencyResolverManager = DependencyResolverManager.Default;
            var dependencyResolver        = _serviceLocator.ResolveType <IDependencyResolver>();

            dependencyResolverManager.RegisterDependencyResolverForInstance(obj, dependencyResolver);

            Log.Debug("Injecting properties into type '{0}' after construction", objectType);

            var type         = obj.GetType();
            var typeMetaData = GetTypeMetaData(type);

            foreach (var injectedProperty in typeMetaData.GetInjectedProperties())
            {
                var propertyInfo    = injectedProperty.Key;
                var injectAttribute = injectedProperty.Value;

                try
                {
                    var dependency = _serviceLocator.ResolveType(injectAttribute.Type, injectAttribute.Tag);
                    propertyInfo.SetValue(obj, dependency, null);
                }
                catch (Exception ex)
                {
                    string error = string.Format("Failed to set property '{0}.{1}' during property dependency injection", type.Name, propertyInfo.Name);
                    Log.Error(ex, error);
                    throw new InvalidOperationException(error);
                }
            }

            var objAsINeedCustomInitialization = obj as INeedCustomInitialization;

            if (objAsINeedCustomInitialization != null)
            {
                objAsINeedCustomInitialization.Initialize();
            }
        }
示例#7
0
        /// <summary>
        /// Unregisters all models of a view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="viewModel"/> is <c>null</c>.</exception>
        public void UnregisterAllModels(IViewModel viewModel)
        {
            Argument.IsNotNull("viewModel", viewModel);

            var viewModelTypeName = ObjectToStringHelper.ToTypeString(viewModel);
            int modelCount        = 0;

            Log.Debug("Unregistering all models of view model '{0}' (id = '{1}')", viewModelTypeName, viewModel.UniqueIdentifier);

            lock (_viewModelModelsLock)
            {
                if (_viewModelModels.TryGetValue(viewModel.UniqueIdentifier, out var models))
                {
                    modelCount = models.Count;
                    _viewModelModels.Remove(viewModel.UniqueIdentifier);
                }
            }

            Log.Debug("Unregistered all '{0}' models of view model '{1}' (id = '{2}')", modelCount, viewModelTypeName, viewModel.UniqueIdentifier);
        }
        /// <summary>
        /// Initializes the specified view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        private void InitializeViewModel(IViewModel viewModel)
        {
            var viewModelType = ObjectToStringHelper.ToTypeString(viewModel);

            Log.Debug("Initializing view model '{0}'", viewModelType);

            UninitializeViewModel(_previousViewModel);

            _previousViewModel = viewModel;

            if (viewModel != null)
            {
                // If there are mappings, sync them in the right way
                var viewModelContainerType = ViewModelContainerType;
                foreach (var mapping in _viewToViewModelMappingContainers[viewModelContainerType].GetAllViewToViewModelMappings())
                {
                    try
                    {
                        if ((mapping.MappingType == ViewToViewModelMappingType.TwoWayViewWins) ||
                            (mapping.MappingType == ViewToViewModelMappingType.ViewToViewModel))
                        {
                            TransferValueFromViewToViewModel(viewModel, mapping.ViewPropertyName, mapping.ViewModelPropertyName);
                        }
                        else if ((mapping.MappingType == ViewToViewModelMappingType.TwoWayViewModelWins) ||
                                 (mapping.MappingType == ViewToViewModelMappingType.ViewModelToView))
                        {
                            TransferValueFromViewModelToView(viewModel, mapping.ViewPropertyName, mapping.ViewModelPropertyName);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Failed to transfer value from view property '{0}' to the view model property '{1}' for the ViewToViewModelMapping",
                                  mapping.ViewPropertyName, mapping.ViewModelPropertyName);
                    }
                }

                viewModel.PropertyChanged += OnViewModelPropertyChanged;
            }

            Log.Debug("Initialized view model '{0}'", viewModelType);
        }
        /// <summary>
        /// Closes the document in the main shell with the specified view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <param name="tag">The tag.</param>
        public void CloseDocument(IViewModel viewModel, object tag = null)
        {
            Argument.IsNotNull(() => viewModel);

            Log.Debug("Closing document for view model '{0}'", viewModel.UniqueIdentifier);

            var viewType = GetViewType(viewModel);
            var document = AvalonDockHelper.FindDocument(viewType, tag);

            if (document == null)
            {
                Log.Warning("Cannot find document belonging to view model '{0}' with id '{1}' thus cannot close the document",
                            ObjectToStringHelper.ToTypeString(viewModel), viewModel.UniqueIdentifier);
            }
            else
            {
                AvalonDockHelper.CloseDocument(document);
            }

            Log.Debug("Closed document for view model '{0}'", viewModel.UniqueIdentifier);
        }
示例#10
0
        /// <summary>
        ///   Generic cast of a value.
        /// </summary>
        /// <typeparam name = "TOutput">Requested return type.</typeparam>
        /// <param name = "value">The value to cast.</param>
        /// <returns>The casted value.</returns>
        public static TOutput Cast <TOutput>(object value)
        {
            TOutput output = default(TOutput);

            if (!TryCast(value, out output))
            {
                var    tI  = ObjectToStringHelper.ToTypeString(value.GetType());
                string tO  = typeof(TOutput).FullName;
                string vl  = string.Concat(value);
                string msg = "Failed to cast from '{0}' to '{1}'";

                if (!tI.Equals(vl))
                {
                    msg = string.Concat(msg, " for value '{2}'");
                }

                msg = string.Format(msg, tI, tO, vl);
                throw new InvalidCastException(msg);
            }

            return(output);
        }
示例#11
0
        /// <summary>
        /// Unregisters all models of a view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="viewModel"/> is <c>null</c>.</exception>
        public void UnregisterAllModels(IViewModel viewModel)
        {
            Argument.IsNotNull("viewModel", viewModel);

            var viewModelTypeName = ObjectToStringHelper.ToTypeString(viewModel);
            int modelCount        = 0;

            Log.Debug("Unregistering all models of view model '{0}' (id = '{1}')", viewModelTypeName, viewModel.UniqueIdentifier);

            lock (_viewModelModelsLock)
            {
                if (!_viewModelModels.ContainsKey(viewModel.UniqueIdentifier))
                {
                    _viewModelModels[viewModel.UniqueIdentifier] = new List <object>();
                }

                var models = _viewModelModels[viewModel.UniqueIdentifier];
                modelCount = models.Count;
                models.Clear();
            }

            Log.Debug("Unregistered all '{0}' models of view model '{1}' (id = '{2}')", modelCount, viewModelTypeName, viewModel.UniqueIdentifier);
        }
示例#12
0
        /// <summary>
        /// Registers the model of a view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <param name="model">The model.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="viewModel"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="model"/> is <c>null</c>.</exception>
        public void RegisterModel(IViewModel viewModel, object model)
        {
            Argument.IsNotNull("viewModel", viewModel);
            Argument.IsNotNull("model", model);

            var viewModelTypeName = ObjectToStringHelper.ToTypeString(viewModel);
            var modelTypeName     = ObjectToStringHelper.ToTypeString(model);

            Log.Debug("Registering model '{0}' with view model '{1}' (id = '{2}')", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);

            lock (_viewModelModelsLock)
            {
                if (!_viewModelModels.TryGetValue(viewModel.UniqueIdentifier, out var models))
                {
                    models = new List <object>();
                    _viewModelModels[viewModel.UniqueIdentifier] = models;
                }

                models.Add(model);
            }

            Log.Debug("Registered model '{0}' with view model '{1}' (id = '{2}')", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);
        }
示例#13
0
        /// <summary>
        /// Unregisters the model of a view model.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <param name="model">The model.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="viewModel"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="model"/> is <c>null</c>.</exception>
        public void UnregisterModel(IViewModel viewModel, object model)
        {
            Argument.IsNotNull("viewModel", viewModel);
            Argument.IsNotNull("model", model);

            var viewModelTypeName = ObjectToStringHelper.ToTypeString(viewModel);
            var modelTypeName     = ObjectToStringHelper.ToTypeString(model);

            Log.Debug("Unregistering model '{0}' with view model '{1}' (id = '{2}')", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);

            lock (_viewModelModelsLock)
            {
                if (!_viewModelModels.ContainsKey(viewModel.UniqueIdentifier))
                {
                    _viewModelModels[viewModel.UniqueIdentifier] = new List <object>();
                }

                var models = _viewModelModels[viewModel.UniqueIdentifier];
                models.Remove(model);
            }

            Log.Debug("Unregistered model '{0}' with view model '{1}' (id = '{2}')", modelTypeName, viewModelTypeName, viewModel.UniqueIdentifier);
        }
示例#14
0
        /// <summary>
        /// Called when the <c>DataContext</c> property of the <see cref="TargetView" /> has changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        public virtual void OnTargetViewDataContextChanged(object sender, DataContextChangedEventArgs e)
        {
            if (IsCurrentDataContext(e))
            {
                return;
            }

            Log.Debug($"DataContext of TargetView '{TargetViewType?.Name}' has changed to '{ObjectToStringHelper.ToTypeString(TargetView.DataContext)}'");

            LastKnownDataContext = null;

            var dataContext = TargetView.DataContext;

            if (ReferenceEquals(dataContext, null))
            {
                return;
            }

            if (dataContext.IsSentinelBindingObject())
            {
                return;
            }

            // Here we have a data context that makes sense
            LastKnownDataContext = new WeakReference(dataContext);

            if (ReferenceEquals(ViewModel, dataContext))
            {
                return;
            }

            // Check if the VM is compatible
            if (_viewModelLocator.IsCompatible(TargetViewType, dataContext.GetType()))
            {
                // Use the view model from the data context, probably set manually
                ViewModel = (IViewModel)dataContext;
            }
        }
示例#15
0
        /// <summary>
        /// Called when the <c>DataContext</c> property of the <see cref="TargetView" /> has changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        public virtual void OnTargetViewDataContextChanged(object sender, DataContextChangedEventArgs e)
        {
            if (e.AreEqual)
            {
                return;
            }

            Log.Debug("DataContext of TargetView '{0}' has changed to '{1}'", TargetView.GetType().Name, ObjectToStringHelper.ToTypeString(TargetView.DataContext));

            var dataContext = TargetView.DataContext;

            if (dataContext == null)
            {
                return;
            }

            if (dataContext.IsSentinelBindingObject())
            {
                return;
            }

            if (ViewModel == dataContext)
            {
                return;
            }

            if (dataContext.GetType().IsAssignableFromEx(ViewModelType))
            {
                // Use the view model from the data context, probably set manually
                ViewModel = (IViewModel)dataContext;
            }
        }
示例#16
0
 public void ReturnsTypeNameForInt()
 {
     Assert.AreEqual("Int32", ObjectToStringHelper.ToTypeString(42));
 }
示例#17
0
 public void ReturnsDbNullStringForDbNullInstance()
 {
     Assert.AreEqual("DBNull", ObjectToStringHelper.ToTypeString(DBNull.Value));
 }
示例#18
0
 public void ReturnsNullStringForNullInstance()
 {
     Assert.AreEqual("null", ObjectToStringHelper.ToTypeString(null));
 }
示例#19
0
        /// <summary>
        /// Gets the view model by its unique identifier.
        /// </summary>
        /// <param name="uniqueIdentifier">The unique identifier.</param>
        /// <returns>The <see cref="IViewModel"/> or <c>null</c> if the view model is not registered.</returns>
        public IViewModel GetViewModel(int uniqueIdentifier)
        {
            Log.Debug("Searching for the instance of view model with unique identifier '{0}'", uniqueIdentifier);

            lock (_managedViewModelsLock)
            {
                foreach (var managedViewModel in _managedViewModels)
                {
                    foreach (var viewModel in managedViewModel.Value.ViewModels)
                    {
                        if (viewModel.UniqueIdentifier == uniqueIdentifier)
                        {
                            Log.Debug("Found the instance of view model with unique identifier '{0}' as type '{1}'", uniqueIdentifier, ObjectToStringHelper.ToTypeString(viewModel));

                            return(viewModel);
                        }
                    }
                }
            }

            Log.Debug("Did not find the instance of view model with unique identifier '{0}'. It is either not registered or not alive.", uniqueIdentifier);

            return(null);
        }
示例#20
0
        /// <summary>
        /// Constructs the view with the view model. First, this method tries to inject the specified DataContext into the
        /// view. If the view does not contain a constructor with this parameter type, it will try to use the default constructor
        /// and set the DataContext manually.
        /// </summary>
        /// <param name="viewType">Type of the view to instantiate.</param>
        /// <param name="dataContext">The data context to inject into the view. In most cases, this will be a view model.</param>
        /// <returns>The constructed view or <c>null</c> if it was not possible to construct the view.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="viewType"/> is <c>null</c>.</exception>
        public static FrameworkElement ConstructViewWithViewModel(Type viewType, object dataContext)
        {
            Argument.IsNotNull("viewType", viewType);

            Log.Debug("Constructing view for view type '{0}'", viewType.Name);

            FrameworkElement view;

            // First, try to constructor directly with the data context
            if (dataContext != null)
            {
                var injectionConstructor = viewType.GetConstructorEx(new[] { dataContext.GetType() });
                if (injectionConstructor != null)
                {
                    view = (FrameworkElement)injectionConstructor.Invoke(new[] { dataContext });

                    Log.Debug("Constructed view using injection constructor");

                    return(view);
                }
            }

            Log.Debug("No constructor with data (of type '{0}') injection found, trying default constructor", ObjectToStringHelper.ToTypeString(dataContext));

            // Try default constructor
            var defaultConstructor = viewType.GetConstructorEx(new Type[0]);

            if (defaultConstructor == null)
            {
                Log.Error("View '{0}' does not have an injection or default constructor thus cannot be constructed", viewType.Name);
                return(null);
            }

            try
            {
                view = (FrameworkElement)defaultConstructor.Invoke(null);
            }
            catch (Exception ex)
            {
                string error = string.Format("Failed to construct view '{0}' with both injection and empty constructor", viewType.Name);
                Log.Error(ex, error);
                throw new InvalidOperationException(error, ex);
            }

            view.DataContext = dataContext;

            Log.Debug("Constructed view using default constructor and setting DataContext afterwards");

            return(view);
        }
示例#21
0
        /// <summary>
        /// Called when the <c>DataContext</c> property of the <see cref="TargetControl"/> has changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        public virtual void OnTargetControlDataContextChanged(object sender, DependencyPropertyValueChangedEventArgs e)
        {
            Log.Debug("DataContext of TargetControl '{0}' has changed to '{1}'", TargetControl.GetType().Name, ObjectToStringHelper.ToTypeString(TargetControl.DataContext));

            var dataContext = TargetControl.DataContext;

            if (dataContext == null)
            {
                return;
            }

            if (BindingHelper.IsSentinelObject(dataContext))
            {
                return;
            }

            if (ViewModel == dataContext)
            {
                return;
            }

            if (dataContext.GetType().IsAssignableFromEx(ViewModelType))
            {
                // Use the view model from the data context, probably set manually
                ViewModel = (IViewModel)dataContext;
            }
        }