|
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ManagedViewModel.cs" company="Catel development team">
// Copyright (c) 2008 - 2011 Catel development team. All rights reserved.
// </copyright>
// <summary>
// Represents a managed view model. A managed view model is watched for property changes. As soon as a change occurs in one of the
// managed view models, all other interested view models are notified of the changes.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Catel.Properties;
using log4net;
namespace Catel.MVVM
{
/// <summary>
/// Represents a managed view model. A managed view model is watched for property changes. As soon as a change occurs in one of the
/// managed view models, all other interested view models are notified of the changes.
/// </summary>
internal class ManagedViewModel
{
#region Variables
/// <summary>
/// The <see cref="ILog">log</see> object.
/// </summary>
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// List of alive view model instances.
/// </summary>
private readonly List<IViewModel> _viewModelInstances = new List<IViewModel>();
/// <summary>
/// List of alive view model instances that are interested in other view models.
/// </summary>
private readonly List<IViewModel> _interestedViewModels = new List<IViewModel>();
#endregion
#region Constructor & destructor
/// <summary>
/// Initializes a new instance of the <see cref="ManagedViewModel"/> class.
/// </summary>
/// <param name="viewModelType">Type of the view model.</param>
public ManagedViewModel(Type viewModelType)
{
ViewModelType = viewModelType;
}
#endregion
#region Properties
/// <summary>
/// Gets the type of the view model.
/// </summary>
/// <value>The type of the view model.</value>
public Type ViewModelType { get; private set; }
#endregion
#region Methods
/// <summary>
/// Adds a view model instance to the list of instances.
/// </summary>
/// <param name="viewModel">The view model instance to add.</param>
/// <exception cref="ArgumentNullException">When <paramref name="viewModel"/> is <c>null</c>.</exception>
/// <exception cref="WrongViewModelTypeException">When <paramref name="viewModel"/> is not of the right type.</exception>
public void AddViewModelInstance(IViewModel viewModel)
{
if (viewModel == null)
{
throw new ArgumentNullException("viewModel");
}
if (viewModel.GetType() != ViewModelType)
{
throw new WrongViewModelTypeException(viewModel.GetType(), ViewModelType);
}
lock (_viewModelInstances)
{
if (!_viewModelInstances.Contains(viewModel))
{
_viewModelInstances.Add(viewModel);
viewModel.PropertyChanged += ViewModel_PropertyChanged;
Log.Debug(TraceMessages.AddedViewModelInstance, _viewModelInstances.Count, ViewModelType);
}
}
}
/// <summary>
/// Removes a view model instance from the list of instances.
/// </summary>
/// <param name="viewModel">The view model instance to remove.</param>
/// <exception cref="ArgumentNullException">When <paramref name="viewModel"/> is <c>null</c>.</exception>
public void RemoveViewModelInstance(IViewModel viewModel)
{
if (viewModel == null)
{
throw new ArgumentNullException("viewModel");
}
lock (_viewModelInstances)
{
viewModel.PropertyChanged -= ViewModel_PropertyChanged;
_viewModelInstances.Remove(viewModel);
Log.Debug(TraceMessages.RemovedViewModelInstance, _viewModelInstances.Count, ViewModelType);
}
}
/// <summary>
/// Adds a view model to the list of interested view models for this view model type.
/// </summary>
/// <param name="viewModel">The view model instance that is interested in changes.</param>
/// <exception cref="ArgumentNullException">When <paramref name="viewModel"/> is <c>null</c>.</exception>
public void AddInterestedViewModel(IViewModel viewModel)
{
if (viewModel == null)
{
throw new ArgumentNullException("viewModel");
}
lock (_interestedViewModels)
{
_interestedViewModels.Add(viewModel);
viewModel.Closed += InterestedViewModel_Closed;
Log.Debug(TraceMessages.AddedInterestedViewModel, viewModel.GetType(), ViewModelType, _interestedViewModels.Count);
}
}
/// <summary>
/// Removes a view model from the list of interested view models for this view model type.
/// </summary>
/// <param name="viewModel">The view model instance that is interested in changes.</param>
/// <exception cref="ArgumentNullException">When <paramref name="viewModel"/> is <c>null</c>.</exception>
public void RemoveInterestedViewModel(IViewModel viewModel)
{
if (viewModel == null)
{
throw new ArgumentNullException("viewModel");
}
lock (_interestedViewModels)
{
viewModel.Closed -= InterestedViewModel_Closed;
_interestedViewModels.Remove(viewModel);
Log.Debug(TraceMessages.RemovedInterestedViewModel, viewModel.GetType(), ViewModelType, _interestedViewModels.Count);
}
}
/// <summary>
/// Handles the PropertyChanged event of the ViewModel instances.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
lock (_interestedViewModels)
{
foreach (ViewModelBaseWithoutServices viewModel in _interestedViewModels)
{
try
{
viewModel.ViewModelPropertyChanged((IViewModel)sender, e.PropertyName);
}
catch (Exception ex)
{
Log.Error(ex, TraceMessages.FailedToInformInterestedViewModelOfAViewModelChange);
}
}
}
}
/// <summary>
/// Handles the Closed event of the InterestedViewModel instances.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void InterestedViewModel_Closed(object sender, EventArgs e)
{
RemoveInterestedViewModel((IViewModel)sender);
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.