UIVisualizer Improvements/Flexiblity

Jun 6, 2012 at 12:25 PM

Hi Geert,

currently i have duplicated the entire catel UIVisializer with modifications to get it work with telerik windows. it would be very helpful if you could make it more flexible for other "window" types (deriving instead of duplication)

here's the modified source code for the standard wpf window... with enough flexibility to adopt it for example for the telerik windows by overriding it instead of duplicating.

   public class UIVisualizerService : ViewModelServiceBase, IUIVisualizerService
        {
            private static readonly ILog Log = LogManager.GetCurrentClassLogger();
            protected readonly Dictionary<string, Type> _registeredWindows = new Dictionary<string, Type>();
            public virtual void Register(Type viewModelType, Type windowType)
            {
                Argument.IsNotNull("viewModelType", viewModelType);
                Argument.IsNotNull("windowType", windowType);
                if (viewModelType.GetInterface(typeof(IViewModel).FullName, false) == null)
                {
                    throw new ArgumentException("Argument must implement IViewModelInterface", "viewModelType");
                }
                this.Register(viewModelType.FullName, windowType);
            }

            public virtual void Register(string name, Type windowType)
            {
                Argument.IsNotNullOrWhitespace("name", name);
                Argument.IsNotNull("windowType", windowType);
                //---------------------------
                if (windowType.IsAssignableFrom(this.WindowType))
                {
                    throw new ArgumentException(string.Format("Argument must be of WindowType {0}", this.WindowType), "windowType");
                }
                //---------------------------
                lock (this._registeredWindows)
                {
                    if (this._registeredWindows.ContainsKey(name))
                    {
                        throw new InvalidOperationException("ViewModel already registered");
                    }
                    this._registeredWindows.Add(name, windowType);
                    UIVisualizerService.Log.Debug("Registered view model '{0}' in combination with '{1}' in the UIVisualizerService", new object[]
				{
					name,
					windowType.FullName
				});
                }
            }

            public bool Unregister(Type viewModelType)
            {
                Argument.IsNotNull("viewModelType", viewModelType);
                return this.Unregister(viewModelType.FullName);
            }

            public virtual bool Unregister(string name)
            {
                bool result2;
                lock (this._registeredWindows)
                {
                    bool result = this._registeredWindows.Remove(name);
                    if (result)
                    {
                        UIVisualizerService.Log.Debug("Unregistered view model '{0}' in UIVisualizerService", new object[]
					{
						name
					});
                    }
                    result2 = result;
                }
                return result2;
            }
            public virtual bool Show(IViewModel viewModel, EventHandler<UICompletedEventArgs> completedProc = null)
            {
                Argument.IsNotNull("viewModel", viewModel);
                string viewModelTypeName = viewModel.GetType().FullName;
                if (!this._registeredWindows.ContainsKey(viewModelTypeName))
                {
                    IViewLocator viewLocator = ServiceLocator.Instance.ResolveType<IViewLocator>();
                    if (viewLocator != null)
                    {
                        Type viewType = viewLocator.ResolveView(viewModel.GetType());
                        if (viewType != null)
                        {
                            this.Register(viewModel.GetType(), viewType);
                        }
                    }
                }
                return this.Show(viewModelTypeName, viewModel, completedProc);
            }

            public virtual bool Show(string name, object data, EventHandler<UICompletedEventArgs> completedProc = null)
            {
                Argument.IsNotNullOrWhitespace("name", name);
                lock (this._registeredWindows)
                {
                    if (!this._registeredWindows.ContainsKey(name))
                    {
                        throw new WindowNotRegisteredException(name);
                    }
                }

                var window = this.CreateWindow(name, data, completedProc, false);
                if (window != null)
                {
                    //---------------------------
                    Show(window);
                    //---------------------------
                }
                return window != null;
            }

            public virtual bool? ShowDialog(IViewModel viewModel, EventHandler<UICompletedEventArgs> completedProc = null)
            {
                Argument.IsNotNull("viewModel", viewModel);
                string viewModelTypeName = viewModel.GetType().FullName;
                if (!this._registeredWindows.ContainsKey(viewModelTypeName))
                {
                    IViewLocator viewLocator = ServiceLocator.Instance.ResolveType<IViewLocator>();
                    if (viewLocator != null)
                    {
                        Type viewType = viewLocator.ResolveView(viewModel.GetType());
                        if (viewType != null)
                        {
                            this.Register(viewModel.GetType(), viewType);
                        }
                    }
                }
                return this.ShowDialog(viewModelTypeName, viewModel, completedProc);
            }

            public virtual bool? ShowDialog(string name, object data, EventHandler<UICompletedEventArgs> completedProc = null)
            {
                Argument.IsNotNullOrWhitespace("name", name);
                lock (this._registeredWindows)
                {
                    if (!this._registeredWindows.ContainsKey(name))
                    {
                        throw new WindowNotRegisteredException(name);
                    }
                }

                var window = this.CreateWindow(name, data, completedProc, true);
                if (window != null)
                {
                    //---------------------------
                    return ShowDialog(window);
                    //---------------------------
                }
                return new bool?(false);
            }
 

            // ------------------------------------
            // ------------------------------------
            // ------------------------------------

            protected virtual bool? ShowDialog(FrameworkElement window)
            {
                Argument.IsNotNull("window", window);
                return ((Window)window).ShowDialog();
            }

            protected virtual void Show(FrameworkElement window)
            {
                Argument.IsNotNull("window", window);
                ((Window)window).Show();              
            }

            protected virtual void SetupWindow(FrameworkElement window, object data, EventHandler<UICompletedEventArgs> completedProc, bool isModal)
            {
                Argument.IsNotNull("window", window);
                if (completedProc != null)
                {
                    DynamicEventListener dynamicEventListener = new DynamicEventListener(window, "Closed");
                    EventHandler closed = null;
                    closed = delegate(object sender, EventArgs e)
                    {
                        bool? dialogResult = null;
                        PropertyHelper.TryGetPropertyValue<bool?>(window, "DialogResult", out dialogResult);
                        completedProc(this, new UICompletedEventArgs(data, isModal ? dialogResult : null));
                        dynamicEventListener.EventOccurred -= closed;
                        dynamicEventListener.UnsubscribeFromEvent();
                    };
                    dynamicEventListener.EventOccurred += closed;
                }
            }

            protected virtual FrameworkElement CreateWindow(object data, EventHandler<UICompletedEventArgs> completedProc, bool isModal)
            {
                var window = ViewHelper.ConstructViewWithViewModel<Window>(this.WindowType, data);
                window.Owner = Application.Current.GetActiveWindow();
                SetupWindow(window, data, completedProc, isModal);
                return window;
            }

            protected virtual FrameworkElement CreateWindow(string name, object data, EventHandler<UICompletedEventArgs> completedProc, bool isModal)
            {
                Type windowType;
                lock (this._registeredWindows)
                {
                    if (!this._registeredWindows.TryGetValue(name, out windowType))
                    {
                        return null;
                    }
                }
                return this.CreateWindow(data, completedProc, isModal);
            }

            protected virtual Type WindowType
            {
                get
                {
                    return typeof(Window);
                }
            }

        }

many thanks!

Jun 6, 2012 at 10:07 PM

I am not sure about this. It seems that you are casting to Window a lot, while the window base type isn't always window. Do you have a cleaner approach? Otherwise I will have to take a closer look at this another time.

Jun 6, 2012 at 10:14 PM

Never mind, I think I fixed it. Can you check it out? I have not released a new nuget build yet, please build it yourself for now (bad internet connection, at least not good enough to release via nuget :))

Jun 7, 2012 at 6:19 PM

yes you are right. my implementation was not dynamic enough... thanks for your corrections.

could you please introduce the following minor modifications:

protected virtual FrameworkElement GetActiveWindow()
{
    return Application.Current.GetActiveWindow();
}


// Line 311:

PropertyHelper.TrySetPropertyValue(window, "Owner", this.GetActiveWindow())

many thanks!

 

 

Jun 7, 2012 at 9:10 PM

Just did, now I will try to create a new nuget package.

Jun 7, 2012 at 9:29 PM

Darn, can't create new nuget packages on this machine. You will have to wait until the weekend.

Jun 8, 2012 at 10:34 AM

no problem, i can wait for it... thanks a lot for the modifications....