How to use Unity Interception to create Attribute Based Cache

1- Download Unity Interception using NuGet.

2- Create a custom attribute

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class CacheAttribute : Attribute
{
    public double AbsoluteExpiration { get; private set; }

    public CacheAttribute(double absoluteExpiration)
    {
        AbsoluteExpiration = absoluteExpiration;
    }
}

3- Create  Interception Behavior

public class CachingInterceptionBehavior : IInterceptionBehavior
{
    private object _LockSync = new object();

    public bool WillExecute
    {
        get
        {
            return true;
        }
    }

    public CachingInterceptionBehavior() { }

    public IEnumerable GetRequiredInterfaces()
    {
        return Type.EmptyTypes;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        IMethodReturn result = null;

        CacheAttribute cacheAttr = input.Target.GetType().GetMethods().FirstOrDefault(m => m.Name == input.MethodBase.Name)
            ?.GetCustomAttributes(typeof(CacheAttribute), false).FirstOrDefault() as CacheAttribute;

        if (cacheAttr != null)
        {
            result = GetItem(input.MethodBase.Name, false) as IMethodReturn;
            if (result == null)
            {
                result = InvokeSource(input, getNext);
                if (result.Exception == null)
                    AddItem(input.MethodBase.Name, result, cacheAttr.AbsoluteExpiration);
            }
        }

        if (result == null)
            result = InvokeSource(input, getNext);

        return result;
    }

    private IMethodReturn InvokeSource(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        return getNext()(input, getNext);
    }

    private void AddItem(string key, object value, double seconds)
    {
        lock (_LockSync)
        {
            MemoryCache.Default.Add(key, value, DateTimeOffset.Now.AddSeconds(seconds));
        }
    }

    private void RemoveItem(string key)
    {
        lock (_LockSync)
        {
            MemoryCache.Default.Remove(key);
        }
    }

    private object GetItem(string key, bool remove)
    {
        lock (_LockSync)
        {
            var res = MemoryCache.Default[key];

            if (res != null)
            {
                if (remove == true)
                    MemoryCache.Default.Remove(key);
            }

            return res;
        }
    }
}

4- Register both the Interception extension and the new Cache behavior

Container.AddNewExtension()
         .RegisterType(new ContainerControlledLifetimeManager());

5- That’s it. It’s time to start decorating your functions

[Cache(absoluteExpiration: 60)]
public async Task GetValue()
{
  .....
}

 

WPF – Display .rft files with RichTextBox using MVVM

1- Xaml


<RichTextBox local:RichTextBoxHelper.DocumentContent="{Binding DocContent}"/>

2- Attached Properties


    public class RichTextBoxHelper : DependencyObject
    {
        public static string GetDocumentContent(DependencyObject obj)
        {
            return (string)obj.GetValue(DocumentContentProperty);
        }

        public static void SetDocumentContent(DependencyObject obj, string value)
        {
            obj.SetValue(DocumentContentProperty, value);
        }

        // Using a DependencyProperty as the backing store for DocumentContent.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DocumentContentProperty =
            DependencyProperty.RegisterAttached("DocumentContent", typeof(string), typeof(RichTextBoxHelper),
                new FrameworkPropertyMetadata
                {
                    BindsTwoWayByDefault = true,
                    PropertyChangedCallback = (obj, e) =>
                    {
                        var richTextBox = (RichTextBox)obj;

                        // Parse the XAML to a document (or use XamlReader.Parse())
                        var xaml = GetDocumentContent(richTextBox);
                        var doc = new FlowDocument();
                        var range = new TextRange(doc.ContentStart, doc.ContentEnd);

                        using (var reader = new MemoryStream(Encoding.UTF8.GetBytes(xaml)))
                        {
                            reader.Position = 0;
                            richTextBox.SelectAll();
                            richTextBox.Selection.Load(reader, DataFormats.Rtf);
                        }
                    }
                });
    }

3- ViewModel


    public class ViewModel
    {
        public string DocContent { get; set; }

        public ViewModel()
        {
            DocContent = File.ReadAllText(@"C:\sample.rtf");
        }
    }

WPF- How to traverse the Visual Tree

How to traverse the Visual Tree to find a control by name


public static T FindChild(DependencyObject parent, string childName)
    where T : DependencyObject
{
    if (parent == null)
        return null;

    T foundChild = null;

    int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < childrenCount; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);

        T childType = child as T;

        if (childType == null)
        {
            foundChild = FindChild(child, childName);
            if (foundChild != null)
                break;
        }
        else if (!string.IsNullOrEmpty(childName))
        {
            FrameworkElement frameworkElement = child as FrameworkElement;

            if (frameworkElement != null && frameworkElement.Name == childName)
            {
                foundChild = (T)child;
                break;
            }
        }
        else
        {
            foundChild = (T)child;
            break;
        }
    }

    return foundChild;
}

How to Find the first parent of a specific type


public static T FindFirstParent(DependencyObject child)
    where T : DependencyObject
{
    if (child == null)
        return null;

    DependencyObject firstParent = null;
    DependencyObject parent = child;
    while (parent != null)
    {
        if (parent is T)
        {
            firstParent = parent;
        }

        parent = VisualTreeHelper.GetParent(parent);
    }

    return firstParent as T;
}

WPF: Timeline control

I had a requirement to implement a timeline control that should somehow resembles the Facebook profile control, and I found it very interesting to implement it from scratch.

I am going to discuss a simplified version of this control. The following figure demonstrates the final look

Timeline

The Idea

It’s so simple. I used a Treeview and a ListBox to achieve the job. I am going to discuss both of them in details, but I want to give a glimpse on how those controls are populated with data.

The Data provider

The control uses a data provider to provide both the Treeview and the ListBox with data comes from the view model through two methods


public interface ITimelineDataProvider
{
    IEnumerable GetMatches(HierarchyData filter);
    IEnumerable GetFilters();
}

The GetFilters method provides the Treeview with filters, so the ListBox could filter out its data according to the Treeview selection.

The GetMatches methods accepts a filter parameter to filter out the data source and assign it to the ListBox.

The TreeView

This controls is responsible to populate years and months (You can change it to whatever you want) on a show/collapse fashion. The control uses a HierarchyData object to track the data level, children and other needed information.


public class HierarchyData : INotifyPropertyChanged
{
    #region Fields
    private bool _IsSelected;
    private bool _IsExpanded;
    #endregion

    #region Properties
    public HierarchyData Parent { get; set; }

    public object Value { get; set; }

    public IEnumerable Children { get; set; }

    public int Level { get; set; }

    public bool HasChildren
    {
        get
        {
            return Children?.Any() ?? false;
        }
    }

    public bool IsSelected
    {
        get { return _IsSelected; }
        set
        {
            _IsSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }

    public bool IsExpanded
    {
        get { return _IsExpanded; }
        set
        {
            _IsExpanded = value;
            OnPropertyChanged("IsExpanded");
        }
    }
    #endregion

    #region INotifyPropertyChanged Implementation
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    #endregion
}

The ListBox

This control is responsible to populate the business object. The associated DataTemplate is given through the main project not by the control itself for re-usability reason. This Test application provides a simple DataEntity object


public class DataEntity
{
    public DateTime Date { get; set; }
    public string Message { get; set; }
}

Download

You can download the control along with a simple test application throughout this link Timelinecontrol.zip (Please remove the .pdf extension to be able to unzip it).

Thank you for reading my post. I hope you enjoyed my control. Please feel free to ask me questions. I will be more than happy to help.

Happy Coding!!!!

How to cancel Listbox/Listview selection using MVVM

If you have a Listbox or a Listview and their SelectedItem are bound to the SelectedItem property in your viewModel. What can you do to cancel a user selection according to a certain VM logic.

The idea

The idea is to Actually change the value and then change it back after the UI thread finishes his operation.

The Implementation

1- Make sure you are using TwoWay binding to your VM Property:

<ListBox SelectedItem="{Binding SelectedItem, Mode=TwoWay}" ......

 

2- Store the original value and restore it back when the UI finishes it’s context operation:


public Session SelectedItem
{
    get { return _SelectedItem; }
    set
    {
        Session originalValue = _SelectedItem;
        MessageBoxResult result = MessageBox.Show("Do you want to ignore current changes?", "Pending changes", MessageBoxButton.YesNo, MessageBoxImage.Question);
        if (result == MessageBoxResult.Cancel)
        {
            _SelectedItem = value;
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                _SelectedItem = originalValue;
                OnPropertyChanged(() => SelectedItem);
            }), DispatcherPriority.ContextIdle, null);

            return;
        }

        SetProperty(ref _SelectedSession, value);
    }
}

I wish this helps. Thank you for reading my post.

Managing Object lifetime using Prism and Unity

 

The Problem:

The problem with PRISM implementation is the lack of control over objects lifetime. Consequently, there is no flexibility to build certain scenarios where you want to dispose your old objects and recreate them again once needed. An example of this, imagine you have a parent view which controls the navigation between its child views, and you want to define a custom behavior to get rid of(Dispose) this parent and all its descendants (including any descendant objects) at the moment you navigate away to a different parent?

I found it impossible to achieve such a scenario with the current implementation, even if you explicitly managed your container lifetime. One reason for that is the Region Manager registers it’s views in a separate view registry which is controlled by the Region Manager itself, leaving no control from the outside.

The Idea:

One of the solutions observed is to extend Prism capabilities to allow the Region Manager to register its views in a container (It could be a child container of a container, I will discuss this later) rather than at its own registry, hence disposing this container, whenever needed, will  dispose its registered view and any other unwelcome dependencies.

Essentially anywhere, which you will be on control of calling Dispose() on the View/View Model in response to some user action (such as a Tab close, or  closing/removing a View) might benefit from using  a child container of a container.

A typical arrangement when using Prism might be something like this:

PRISM module

The Solution:

Here is what I did:

  1. Extend the Region Manager with two more functionalities:
    • RequestNavigateUsingContainer: This function replaces RegionManager.RequestNavigate, and it does the following, it uses the given container as a source of view repository to request navigate from.
    • RequestNavigateToDisposableView: This function replaces RegionManager.RequestNavigate as well, and it does the following:
      • Creates a child container of the given container.
      • Uses the new container to register an instance of the required view.
      • Navigates to this view using the new container.
  2. Extend Unity with RegisterViewForNavigation function: A function to register a type of view to be used later with navigation (You should use this function in conjunction with RequestNavigateUsingContainer discussed above). IMPORTNAT: When using the Unity container the registering against the typeof(Object) is a vital part of the registration. If you do not use this function to register your objects, you will likely just get the View name shown as a string representation rather than the actual View.
  3. Extend RegionNavigationContentLoader and RegionNavigationService to allow navigation using a container.
  4. Extend the Region Behavior with functionality to dispose both the view and it’s view model once a delete is detected at Region Manager view collection: This helper behavior will fetch the view and it’s view model and call the dispose method on both of them when it detects a view is being deleted from the view collection (Deleting a view from the view collection is the job of the DisposableView class. Defined at #7).
  5. Configured Prism to use the following: (Including the required references to ask Prism to adhere the new extension in the Bootstrapper class)
    • The new NavigationContentLoader and the new RegionNavigationService.
    • The new Region Behavior.
  6. Created a DisposableView class to be used as a parent for any disposable view: This class holds a reference to the View’s container, and it’s of removing itself from the view collection as well as disposing the holding container.

 

How to Use:

The first thing to do is, you need to build your chart on how you want to keep/dispose your objects:

  • If you decide to keep a certain view a live, here is what you can do:
    • Register a type of your view using RegisterViewForNavigation method (It needs to be registered using the HierarchicalLifetimeManager if you want it to be disposed when the holding container is disposed).
    • Use the RequestNavigateUsingContainer (Defined at #1 a) to request navigate to this view.
  • If you want your view to get disposed every time you navigate back and forth (Disposable View), here is what you can do:
    • Make your view Inherits from DisposableView (Defined at #6)
    • Use the RequestNavigateToDisposableView(Defined at #1 b) to navigate to this view.

IMPORTANT: Please don’t use RegionManager.RegisterViewWithRegion nor RegionManager.RequestNavigate. The whole idea is to replace those methods and override their behavior, I could have re-implemented them with the new behavior, but I chose not to because maybe you think that the current implementation is sufficient for your situation.

Best Practice in case of  Independent Module:

If you have an independent module (Its life time is not based on other Modules, I would strongly recommend to create a Disposable Parent View for this module (Acts as a wrapper for all your defined views). The benefit of this approach is to avoid any memory leak and to guarantee the complete memory release of all the objects owned by this module once you navigate to another module, you also will free up the space allocated in the memory for this module.

Download

I have written a class library that extends PRISM with functionality discussed above along with a simple example. You can download it from this link(Prism.Extension.Example.zip). You need to remove .pdf extension to be able to unzip it.

References

  1. Prism 5.0 source code
  2. ViewModel-st-Child-Container-PRISM-Navigation

 

Thank you for reading my post. I tried to make it as clear as I could, but in case I failed, Please don’t hesitate to ask me.