internal async Task <bool> NavigateInternal <TResult>(IViewModel viewModel, Func <TResult, Task> callback1, Func <Task> callback2) { try { var viewModelType = viewModel.GetType(); Tuple <Window, bool> windowInfo = null; // Check if the view model has a defined view var viewAttrib = viewModelType.GetCustomAttribute <ViewAttribute>(false); if (viewAttrib != null && viewAttrib.ViewType != null) { // Create the view - use the activator, since we dont expect any code in the view windowInfo = await this.CreateDefaultWindow(callback1, callback2, Factory.Create(viewAttrib.ViewType) as FrameworkElement, viewModel); } else if (viewAttrib != null && !string.IsNullOrEmpty(viewAttrib.ViewName)) { windowInfo = await this.CreateWindow(viewModel, callback1, callback2, viewAttrib.ViewName); } else // The viewmodel does not have a defined view... Maybe we have a data template instead // If we dont have a dataTemplate... we try to find a matching FrameworkElement { windowInfo = await this.CreateWindow(viewModel, callback1, callback2, viewModelType.Name); } var window = windowInfo.Item1; (viewModel as IDisposableObject).IsNotNull(x => x.Disposed += async(s, e) => await viewModel.Dispatcher.RunAsync(() => window.Close())); window.Closing += Window_Closing; window.Closed += (s, e) => (viewModel as ICloseAwareViewModel).IsNotNull(x => x.Close()); window.Activated += (s, e) => { // This only applies to windows that are not maximized if (window.WindowState != WindowState.Maximized) { // Check if the window is visible for the user If the user has for example // undocked his laptop (which means he lost a monitor) and the application // was running on the secondary monitor, we can't just start the window with // that configuration if (!MonitorInfo.WindowIsInAnyMonitor(window.GetWindowHandle())) { var source = PresentationSource.FromVisual(window); var primaryBounds = MonitorInfo.PrimaryMonitorBounds; window.Height = Math.Min(window.Height, primaryBounds.Height); window.Width = Math.Min(window.Width, primaryBounds.Width); window.Left = Math.Max(0, (primaryBounds.Width / source.CompositionTarget.TransformToDevice.M11 / 2) - (window.Width / 2)); window.Top = Math.Max(0, (primaryBounds.Height / source.CompositionTarget.TransformToDevice.M22 / 2) - (window.Height / 2)); } else { // we have to make sure, that the title bar of the window is visible for // the user var monitorBounds = MonitorInfo.GetMonitorBounds(window.GetWindowHandle()); if (monitorBounds.HasValue) { window.Height = Math.Min(window.Height, monitorBounds.Value.Height); window.Width = Math.Min(window.Width, monitorBounds.Value.Width); window.Left = window.Left >= monitorBounds.Value.Left && window.Left <= monitorBounds.Value.Right ? window.Left : monitorBounds.Value.Left; window.Top = window.Top >= monitorBounds.Value.Top && window.Top <= monitorBounds.Value.Bottom ? window.Top : monitorBounds.Value.Top; } else // set the left and top to 0 { window.Left = 0; window.Top = 0; } } } }; if (windowInfo.Item2) { window.ShowDialog(); } else { window.Show(); } return(true); } catch (XamlParseException) { throw; } catch (NullReferenceException) { throw; } catch (Exception e) { Debug.WriteLine(e); return(false); } }
internal async Task <bool> NavigateInternal <TResult>(IViewModel viewModel, Func <TResult, Task> callback1, Func <Task> callback2) { try { var viewModelType = viewModel.GetType(); Tuple <Window, bool> windowInfo; // Check if the view model has a defined view var viewAttrib = viewModelType.GetCustomAttribute <ViewAttribute>(false); if (viewAttrib != null) { // Create the view - use the activator, since we dont expect any code in the view windowInfo = await CreateDefaultWindow(callback1, callback2, Factory.Create(viewAttrib.ViewType) as FrameworkElement, viewModel); } else // The viewmodel does not have a defined view... Maybe we have a data template instead { // we always prefer our selector, because it rocks var templateSelector = Application.Current.Resources[typeof(CauldronTemplateSelector).Name] as DataTemplateSelector; var dataTemplate = templateSelector.SelectTemplate(viewModel, null); // If we dont have a dataTemplate... we try to find a matching FrameworkElement if (dataTemplate == null) { var possibleViewName = viewModelType.Name.Left(viewModelType.Name.Length - "Model".Length); var possibleView = Factory.Create(possibleViewName) ?? Factory.Create(Assemblies.GetTypeFromName(possibleViewName)); // On such case we create a dummy View if (possibleView == null) { var textBlock = new TextBlock(); textBlock.Text = viewModelType.FullName; textBlock.Foreground = new SolidColorBrush(Colors.Tomato); textBlock.TextWrapping = TextWrapping.NoWrap; textBlock.TextTrimming = TextTrimming.CharacterEllipsis; textBlock.FontSize = 18; windowInfo = await CreateDefaultWindow(callback1, callback2, textBlock, viewModel); } else { windowInfo = await CreateDefaultWindow(callback1, callback2, possibleView as FrameworkElement, viewModel); } } else { // try to get a WindowConfiguration attach in the datatemplate windowInfo = await CreateDefaultWindow(callback1, callback2, dataTemplate.LoadContent() as FrameworkElement, viewModel); } } var window = windowInfo.Item1; (viewModel as IDisposableObject).IsNotNull(x => x.Disposed += async(s, e) => await viewModel.Dispatcher.RunAsync(() => window.Close())); window.Closing += (s, e) => { var closeAware = viewModel as ICloseAwareViewModel; if (closeAware != null) { e.Cancel = !closeAware.CanClose(); } }; window.Closed += (s, e) => (viewModel as ICloseAwareViewModel).IsNotNull(x => x.Close()); window.Activated += (s, e) => { // This only applies to windows that are not maximized if (window.WindowState != WindowState.Maximized) { // Check if the window is visible for the user If the user has for example // undocked his laptop (which means he lost a monitor) and the application // was running on the secondary monitor, we can't just start the window with // that configuration if (!MonitorInfo.WindowIsInAnyMonitor(window.GetWindowHandle())) { var source = PresentationSource.FromVisual(window); var primaryBounds = MonitorInfo.PrimaryMonitorBounds; window.Height = Math.Min(window.Height, primaryBounds.Height); window.Width = Math.Min(window.Width, primaryBounds.Width); window.Left = Math.Max(0, (primaryBounds.Width / source.CompositionTarget.TransformToDevice.M11 / 2) - (window.Width / 2)); window.Top = Math.Max(0, (primaryBounds.Height / source.CompositionTarget.TransformToDevice.M22 / 2) - (window.Height / 2)); } else { // we have to make sure, that the title bar of the window is visible for // the user var monitorBounds = MonitorInfo.GetMonitorBounds(window.GetWindowHandle()); if (monitorBounds.HasValue) { window.Height = Math.Min(window.Height, monitorBounds.Value.Height); window.Width = Math.Min(window.Width, monitorBounds.Value.Width); window.Left = window.Left >= monitorBounds.Value.Left && window.Left <= monitorBounds.Value.Right ? window.Left : monitorBounds.Value.Left; window.Top = window.Top >= monitorBounds.Value.Top && window.Top <= monitorBounds.Value.Bottom ? window.Top : monitorBounds.Value.Top; } else // set the left and top to 0 { window.Left = 0; window.Top = 0; } } } }; if (windowInfo.Item2) { window.ShowDialog(); } else { window.Show(); } return(true); } catch (XamlParseException) { throw; } catch (NullReferenceException) { throw; } catch (Exception e) { Output.WriteLineError(e.GetStackTrace()); return(false); } }