aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs
blob: 879401c1b191309289e9bc17677131e13a7b84c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Tango.BL;
using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.BL.ValueObjects;
using Tango.Core.Commands;
using Tango.Core.ExtensionMethods;
using Tango.MachineStudio.Common;
using Tango.MachineStudio.Common.Notifications;
using Tango.SharedUI.Components;

namespace Tango.MachineStudio.ActionLogs.ViewModels
{
    public class MainViewVM : StudioViewModel
    {
        private INotificationProvider _notification;
        private List<User> _allUsers;

        #region Properties

        private DateTime _startSelectedDate;
        public DateTime StartSelectedDate
        {
            get { return _startSelectedDate; }
            set { _startSelectedDate = value; RaisePropertyChangedAuto(); }
        }

        private DateTime _endSelectedDate;
        public DateTime EndSelectedDate
        {
            get { return _endSelectedDate; }
            set { _endSelectedDate = value; RaisePropertyChangedAuto(); }
        }

        private string _searchFilter;
        public string SearchFilter
        {
            get { return _searchFilter; }
            set { _searchFilter = value; RaisePropertyChangedAuto(); }
        }

        private ObservableCollection<ActionLog> _actionLogs;
        public ObservableCollection<ActionLog> ActionLogs
        {
            get { return _actionLogs; }
            set { _actionLogs = value; RaisePropertyChanged(nameof(ActionLogs)); }
        }

        private SelectedObjectCollection<ActionLogType> _selectedActionLogTypes;
        public SelectedObjectCollection<ActionLogType> SelectedActionLogTypes
        {
            get { return _selectedActionLogTypes; }
            set
            {
                _selectedActionLogTypes = value;
                RaisePropertyChanged(nameof(SelectedActionLogTypes));
            pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using Tango.Core;
using Tango.SharedUI.Helpers;

namespace Tango.SharedUI.Controls
{
    [ContentProperty(nameof(Elements))]
    public class NavigationControl : UserControl
    {
        private event Action NavigationCompleted;
        public event EventHandler<FrameworkElement> SelectedElementChanged;
        private Thread _navigationThread;
        private bool _preventSelectedObjectNavigation;
        private ProducerConsumerQueue<NavigationQueueItem> _navigationQueue;

        private class NavigationQueueItem
        {
            public NavigationElement FromElement { get; set; }
            public NavigationElement ToElement { get; set; }
        }

        #region Transition Types

        public enum TransitionTypes
        {
            Fade,
            Zoom,
            Slide,
        }

        #endregion

        #region Navigation Element

        private class NavigationElement : ContentControl
        {
            public FrameworkElement Element
            {
                get { return (FrameworkElement)GetValue(ElementProperty); }
                set { SetValue(ElementProperty, value); }
            }
            public static readonly DependencyProperty ElementProperty =
                DependencyProperty.Register("Element", typeof(FrameworkElement), typeof(NavigationControl), new PropertyMetadata(null));

            public ScaleTransform Scale
            {
                get { return (ScaleTransform)GetValue(ScaleProperty); }
                set { SetValue(ScaleProperty, value); }
            }
            public static readonly DependencyProperty ScaleProperty =
                DependencyProperty.Register("Scale", typeof(ScaleTransform), typeof(NavigationControl), new PropertyMetadata(null));

            public RotateTransform Rotate
            {
                get { return (RotateTransform)GetValue(RotateProperty); }
                set { SetValue(RotateProperty, value); }
            }
            public static readonly DependencyProperty RotateProperty =
                DependencyProperty.Register("Rotate", typeof(RotateTransform), typeof(NavigationControl), new PropertyMetadata(null));

            public TranslateTransform Translate
            {
                get { return (TranslateTransform)GetValue(TranslateProperty); }
                set { SetValue(TranslateProperty, value); }
            }
            public static readonly DependencyProperty TranslateProperty =
                DependencyProperty.Register("Translate", typeof(TranslateTransform), typeof(NavigationControl), new PropertyMetadata(null));

            public NavigationElement()
            {
                Visibility = Visibility.Hidden;

                Scale = new ScaleTransform(1, 1);
                Rotate = new RotateTransform(0);
                Translate = new TranslateTransform(0, 0);

                TransformGroup group = new TransformGroup();
                group.Children.Add(Scale);
                group.Children.Add(Rotate);
                group.Children.Add(Translate);

                RenderTransformOrigin = new Point(0.5, 0.5);
                RenderTransform = group;
            }

            public NavigationElement(FrameworkElement element) : this()
            {
                Element = element;
            }

            public void AnimateScale(DoubleAnimation animation)
            {
                Scale.BeginAnimation(ScaleTransform.ScaleXProperty, animation);
                Scale.BeginAnimation(ScaleTransform.ScaleYProperty, animation);
            }

            public void AnimateTranslateX(DoubleAnimation animation)
            {
                Translate.BeginAnimation(TranslateTransform.XProperty, animation);
            }

            public void AnimateOpacity(DoubleAnimation animation)
            {
                BeginAnimation(OpacityProperty, animation);
            }

            public void Reset()
            {
                Scale.BeginAnimation(ScaleTransform.ScaleXProperty, null);
                Scale.BeginAnimation(ScaleTransform.ScaleYProperty, null);
                Rotate.BeginAnimation(RotateTransform.AngleProperty, null);
                Translate.BeginAnimation(TranslateTransform.XProperty, null);
                Translate.BeginAnimation(TranslateTransform.YProperty, null);
                Opacity = 1;
            }

            public void Activate()
            {
                if (Content != Element)
                {
                    Content = Element;
                }

                Visibility = Visibility.Visible;
            }

            public void Deactivate(bool detach)
            {
                if (detach)
                {
                    Content = null;
                }

                Visibility = Visibility.Hidden;
            }
        }

        #endregion

        #region INavigationView

        public interface INavigationView
        {
            void OnNavigatedTo();
            void OnNavigatedFrom();
        }

        #endregion

        #region INavigationViewModel

        /// <summary>
        /// Represents a view data context which can be notified when its view is being navigated in or out.
        /// </summary>
        public interface INavigationViewModel
        {
            /// <summary>
            /// Called when the navigation system has navigated to this VM view.
            /// </summary>
            void OnNavigatedTo();

            /// <summary>
            /// Called when the navigation system has navigated from this VM view.
            /// </summary>
            void OnNavigatedFrom();
        }

        #endregion

        private Grid _grid;
        private bool _loaded;

        #region Properties



        public object SelectedObject
        {
            get { return (object)GetValue(SelectedObjectProperty); }
            set { SetValue(SelectedObjectProperty, value); }
        }
        public static readonly DependencyProperty SelectedObjectProperty =
            DependencyProperty.Register("SelectedObject", typeof(object), typeof(NavigationControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (d, e) => (d as NavigationControl).OnSelectedObjectChanged()));

        private void OnSelectedObjectChanged()
        {
            if (SelectedObject != null && !_preventSelectedObjectNavigation)
            {
                NavigateTo(SelectedObject);
            }
        }

        public ObservableCollection<FrameworkElement> Elements
        {
            get { return (ObservableCollection<FrameworkElement>)GetValue(ElementsProperty); }
            set { SetValue(ElementsProperty, value); }
        }
        public static readonly DependencyProperty ElementsProperty =
            DependencyProperty.Register("Elements", typeof(ObservableCollection<FrameworkElement>), typeof(NavigationControl), new PropertyMetadata(null, (d, e) => (d as NavigationControl).OnElementsChanged()));

        public FrameworkElement SelectedElement
        {
            get { return (FrameworkElement)GetValue(SelectedElementProperty); }
            set { SetValue(SelectedElementProperty, value); }
        }
        public static readonly DependencyProperty SelectedElementProperty =
            DependencyProperty.Register("SelectedElement", typeof(FrameworkElement), typeof(NavigationControl), new FrameworkPropertyMetadata(null, (d, e) => (d as NavigationControl).OnSelectedElementChanged(e.OldValue as FrameworkElement, e.NewValue as FrameworkElement)));

        public TransitionTypes TransitionType
        {
            get { return (TransitionTypes)GetValue(TransitionTypeProperty); }
            set { SetValue(TransitionTypeProperty, value); }
        }
        public static readonly DependencyProperty TransitionTypeProperty =
            DependencyProperty.Register("TransitionType", typeof(TransitionTypes), typeof(NavigationControl), new PropertyMetadata(TransitionTypes.Zoom));

        public bool TransitionAlwaysFades
        {
            get { return (bool)GetValue(TransitionAlwaysFadesProperty); }
            set { SetValue(TransitionAlwaysFadesProperty, value); }
        }
        public static readonly DependencyProperty TransitionAlwaysFadesProperty =
            DependencyProperty.Register("TransitionAlwaysFades", typeof(bool), typeof(NavigationControl), new PropertyMetadata(false));

        public Duration TransitionDuration
        {
            get { return (Duration)GetValue(TransitionDurationProperty); }
            set { SetValue(TransitionDurationProperty, value); }
        }
        public static readonly DependencyProperty TransitionDurationProperty =
            DependencyProperty.Register("TransitionDuration", typeof(Duration), typeof(NavigationControl), new PropertyMetadata(new Duration(TimeSpan.FromSeconds(0.5))));

        public bool KeepElementsAttached
        {
            get { return (bool)GetValue(KeepElementsAttachedProperty); }
            set { SetValue(KeepElementsAttachedProperty, value); }
        }
        public static readonly DependencyProperty KeepElementsAttachedProperty =
            DependencyProperty.Register("KeepElementsAttached", typeof(bool), typeof(NavigationControl), new PropertyMetadata(false));



        public int SelectedIndex
        {
            get { return (int)GetValue(SelectedIndexProperty); }
            set { SetValue(SelectedIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedIndex.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedIndexProperty =
            DependencyProperty.Register("SelectedIndex", typeof(int), typeof(NavigationControl), new PropertyMetadata(0, (d, e) => (d as NavigationControl).OnSelectedIndexChanged()));

        public bool UseDefferedRendering
        {
            get { return (bool)GetValue(UseDefferedRenderingProperty); }
            set { SetValue(UseDefferedRenderingProperty, value); }
        }
        public static readonly DependencyProperty UseDefferedRenderingProperty =
            DependencyProperty.Register("UseDefferedRendering", typeof(bool), typeof(NavigationControl), new PropertyMetadata(false));



        private void OnSelectedIndexChanged()
        {
            SelectedElement = Elements[SelectedIndex > Elements.Count - 1 ? 0 : SelectedIndex];
        }

        #endregion

        #region Attached Properties

        #region NavigationName

        /// <summary>
        /// Determines the element navigation name.
        /// </summary>
        public static readonly DependencyProperty NavigationName =
            DependencyProperty.RegisterAttached("NavigationName",
            typeof(String), typeof(NavigationControl),
            new FrameworkPropertyMetadata(""));

        /// <summary>
        /// Sets the name of the navigation.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="value">The value.</param>
        public static void SetNavigationName(FrameworkElement element, String value)
        {
            element.SetValue(NavigationName, value);
        }

        /// <summary>
        /// Gets the name of the navigation.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        public static String GetNavigationName(FrameworkElement element)
        {
            var name = element.GetValue(NavigationName).ToStringSafe();
            if (String.IsNullOrEmpty(name)) name = element.GetType().Name;
            return name;
        }

        #endregion

        #endregion

        #region Constructors

        public NavigationControl()
        {
            ClipToBounds = true;
            _grid = new Grid();
            Content = _grid;
            Elements = new ObservableCollection<FrameworkElement>();
            Loaded += NavigationControl_Loaded;

            _navigationQueue = new ProducerConsumerQueue<NavigationQueueItem>();
            _navigationThread = new Thread(NavigationThread);
            _navigationThread.IsBackground = true;
            _navigationThread.Start();
        }

        #endregion

        #region Event Handlers

        private void NavigationControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (!_loaded)
            {
                _loaded = true;

                if (Elements != null)
                {
                    //foreach (var element in Elements.Where(x => x != SelectedElement))
                    //{
                    //    LoadVisual(element);
                    //}

                    SelectedElement = Elements.FirstOrDefault();
                }
            }
        }

        private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            SyncElements();
        }

        #endregion

        #region Private Methods

        private void OnElementsChanged()
        {
            if (Elements != null)
            {
                Elements.CollectionChanged -= Elements_CollectionChanged;
                Elements.CollectionChanged += Elements_CollectionChanged;
            }

            SyncElements();
        }

        private void SyncElements()
        {
            if (Elements == null)
            {
                _grid.Children.Clear();
            }
            else
            {
                Elements.ToList().ForEach(x => x.FocusVisualStyle = null);

                var toRemove = _grid.Children.OfType<NavigationElement>().ToList().Where(x => !Elements.Contains(x.Element)).ToList();
                var toAdd = Elements.Where(x => !_grid.Children.OfType<NavigationElement>().Select(y => y.Element).ToList().Contains(x)).ToList();

                toRemove.ForEach(x => _grid.Children.Remove(x));

                if (UseDefferedRendering)
                {
                    foreach (var x in toAdd)
                    {
                        var navigationElement = new NavigationElement()
                        {
                            RenderTransformOrigin = new Point(0.5, 0.5),
                            Element = x,
                            Content = x,
                        };

                        _grid.Children.Add(navigationElement);

                        if (!KeepElementsAttached)
                        {
                            bool loaded = false;

                            navigationElement.Loaded += (_, __) =>
                            {
                                if (!loaded)
                                {
                                    if (x != SelectedElement)
                                    {
                                        loaded = true;
                                        navigationElement.Content = null;
                                    }
                                }
                            };
                        }
                    }
                }
                else
                {
                    toAdd.ForEach(x => _grid.Children.Add(
                    new NavigationElement()
                    {
                        RenderTransformOrigin = new Point(0.5, 0.5),
                        Element = x,
                        Content = KeepElementsAttached ? x : null,
                    }));
                }
            }

            if (!Elements.Contains(SelectedElement))
            {
                SelectedElement = null;
            }
        }

        private NavigationElement GetElementContainer(FrameworkElement element)
        {
            return _grid.Children.OfType<NavigationElement>().ToList().SingleOrDefault(x => x.Element == element);
        }

        private void Navigate(NavigationElement fromElement, NavigationElement toElement)
        {
            _navigationQueue.BlockEnqueue(new NavigationQueueItem()
            {
                FromElement = fromElement,
                ToElement = toElement,
            });
        }

        private void NavigationThread()
        {
            try
            {
                while (true)
                {
                    var item = _navigationQueue.BlockDequeue();

                    var navigationCompleted = false;

                    NavigationElement fromElement = item.FromElement;
                    NavigationElement toElement = item.ToElement;

                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        if (toElement == null || toElement == fromElement)
                        {
                        //navigationCompleted = true;
                        Debug.WriteLine("NavigationControl: THIS MIGHT CAUSE PROBLEMS !!");
                        }

                        if (fromElement != null)
                        {
                            DoubleAnimation toAnimation = new DoubleAnimation();
                            toAnimation.Duration = TransitionDuration;

                            DoubleAnimation fromAnimation = new DoubleAnimation();
                            fromAnimation.Duration = TransitionDuration;

                            int fromIndex = Elements.IndexOf(fromElement.Element);
                            int toIndex = Elements.IndexOf(toElement.Element);

                            fromElement.Reset();
                            toElement.Reset();

                            fromAnimation.Completed += (_, __) =>
                            {
                                fromElement.Deactivate(!KeepElementsAttached);
                            };

                            bool completed = false;

                            toAnimation.Completed += (_, __) =>
                            {
                                if (!completed)
                                {
                                    completed = true;

                                    INavigationView fromNavigationView = fromElement.Element as INavigationView;
                                    INavigationView toNavigationView = toElement.Element as INavigationView;

                                    if (fromNavigationView != null)
                                    {
                                        fromNavigationView.OnNavigatedFrom();
                                    }
                                    if (toNavigationView != null)
                                    {
                                        toNavigationView.OnNavigatedTo();
                                    }

                                    INavigationViewModel fromVM = fromElement.Element.DataContext as INavigationViewModel;
                                    INavigationViewModel toVM = toElement.Element.DataContext as INavigationViewModel;

                                    if (fromVM != null && fromVM != toVM) fromVM.OnNavigatedFrom();
                                    if (toVM != null) toVM.OnNavigatedTo();

                                    navigationCompleted = true;
                                }
                            };

                            switch (TransitionType)
                            {
                                case TransitionTypes.Fade:
                                    fromAnimation.From = 1;
                                    fromAnimation.To = 0;

                                    toAnimation.From = 0;
                                    toAnimation.To = 1;

                                    fromElement.AnimateOpacity(fromAnimation);
                                    toElement.AnimateOpacity(toAnimation);

                                    break;
                                case TransitionTypes.Zoom:
                                    fromAnimation.From = 1;
                                    fromAnimation.To = 0;

                                    toAnimation.From = 0;
                                    toAnimation.To = 1;

                                    fromElement.AnimateScale(fromAnimation);
                                    toElement.AnimateScale(toAnimation);

                                    break;
                                case TransitionTypes.Slide:

                                    if (toIndex > fromIndex)
                                    {
                                        fromAnimation.From = 0;
                                        fromAnimation.To = -ActualWidth;

                                        toAnimation.From = ActualWidth;
                                        toAnimation.To = 0;
                                    }
                                    else
                                    {
                                        fromAnimation.From = 0;
                                        fromAnimation.To = ActualWidth;

                                        toAnimation.From = -ActualWidth;
                                        toAnimation.To = 0;
                                    }

                                    fromElement.AnimateTranslateX(fromAnimation);
                                    toElement.AnimateTranslateX(toAnimation);

                                    break;
                            }

                            if (TransitionAlwaysFades && TransitionType != TransitionTypes.Fade)
                            {
                                DoubleAnimation fromFadeAnimation = new DoubleAnimation();
                                fromFadeAnimation.From = 1;
                                fromFadeAnimation.To = 0;
                                fromFadeAnimation.Duration = TransitionDuration;

                                DoubleAnimation toFadeAnimation = new DoubleAnimation();
                                toFadeAnimation.From = 0;
                                toFadeAnimation.To = 1;
                                toFadeAnimation.Duration = TransitionDuration;

                                fromElement.AnimateOpacity(fromFadeAnimation);
                                toElement.AnimateOpacity(toFadeAnimation);
                            }

                            fromElement.Activate();
                            toElement.Activate();
                        }
                        else
                        {
                            toElement.Activate();
                            toElement.Reset();

                            INavigationViewModel toVM = toElement.Element.DataContext as INavigationViewModel;
                            if (toVM != null) toVM.OnNavigatedTo();

                            navigationCompleted = true;
                        }
                    }));

                    for (int i = 0; i < 30; i++)
                    {
                        if (navigationCompleted)
                        {
                            break;
                        }
                        Thread.Sleep(100);
                    }

                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        NavigationCompleted?.Invoke();
                    }));
                }
            }
            catch
            {
                
            }
        }

        #endregion

        #region Properties Changes

        protected virtual void OnSelectedElementChanged(FrameworkElement fromElement, FrameworkElement toElement)
        {
            Navigate(GetElementContainer(fromElement), GetElementContainer(toElement));
            SelectedElementChanged?.Invoke(this, toElement);

            if (toElement != null)
            {
                _preventSelectedObjectNavigation = true;
                SelectedObject = GetNavigationName(toElement);
                _preventSelectedObjectNavigation = false;
            }
        }

        #endregion

        #region Public Methods

        public void NavigateTo(FrameworkElement element)
        {
            var e = Elements.SingleOrDefault(x => x == element);

            if (e != null)
            {
                SelectedElement = element;
            }
        }

        public FrameworkElement NavigateTo(String navigationName)
        {
            return NavigateTo(navigationName, null);
        }

        public FrameworkElement NavigateTo(Object obj)
        {
            return NavigateTo(obj.ToString(), null);
        }

        public FrameworkElement NavigateTo(String navigationName, Action onCompleted = null)
        {
            Action completed = null;

            completed = () =>
            {
                try
                {
                    onCompleted?.Invoke();
                }
                catch { }
                NavigationCompleted -= completed;
            };

            NavigationCompleted += completed;

            var element = Elements.SingleOrDefault(x => GetNavigationName(x) == navigationName || x.GetType().Name == navigationName);

            Task.Factory.StartNew(() =>
            {
                Thread.Sleep(10);

                Dispatcher.BeginInvoke(new Action(async () =>
                {
                    if (element != null)
                    {
                        if (SelectedElement == element)
                        {
                            await Task.Delay((int)TransitionDuration.TimeSpan.TotalMilliseconds * 2);
                            NavigationCompleted?.Invoke();
                        }
                        else
                        {
                            SelectedElement = element;
                        }
                    }
                }));
            });

            return element;
        }

        public Task<FrameworkElement> NavigateToAsync(String navigationName)
        {
            TaskCompletionSource<FrameworkElement> source = new TaskCompletionSource<FrameworkElement>();

            FrameworkElement view = null;

            view = NavigateTo(navigationName, () =>
            {
                source.SetResult(view);
            });

            return source.Task;
        }

        public FrameworkElement GetElement(String navigationName)
        {
            return Elements.SingleOrDefault(x => GetNavigationName(x) == navigationName || x.GetType().Name == navigationName);
        }

        public FrameworkElement GetAndDetach(String navigationName)
        {
            var element = Elements.SingleOrDefault(x => GetNavigationName(x) == navigationName);
            GetElementContainer(element).Deactivate(!KeepElementsAttached);
            return element;
        }

        public String GetSelectedElementNavigationName()
        {
            return GetNavigationName(SelectedElement);
        }

        /// <remarks>
        /// This method needs to be called in order for 
        //  the element to print visibly at the correct size.
        /// </remarks>
        private static void LoadVisual(FrameworkElement element)
        {
            if (element.Parent == null)
            {
                try
                {
                    System.Windows.Forms.UserControl controlContainer = new System.Windows.Forms.UserControl();
                    controlContainer.Width = 100;
                    controlContainer.Height = 100;
                    var host = new ElementHost() { Child = element, Dock = System.Windows.Forms.DockStyle.Fill };
                    controlContainer.Controls.Add(host);
                    IntPtr handle = controlContainer.Handle;
                    host.Child = null;
                    controlContainer.Dispose();
                }
                catch { }
            }
        }
        #endregion
    }
}