Wednesday, May 20, 2015

WPF Shellview Customizable WindowResizeGrip

//NOTE: This sample is for a WPF Main ShellView utilizing a fully customized header bar with Minimize & Maximize buttons, which allows the application user to grip the main form and resize to their heart's desire.

<Window x:Class="myApp.MainForm.Views.ShellView" IsEnabled="{Binding myBindingActivationVar,Mode=OneWay}"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

        ...
        WindowState="Maximized" WindowStyle="None" WindowStartupLocation="CenterScreen"
        SizeToContent="Manual" Icon="/myAppIcon.ico" Title="myApp MainForm" Padding="0" Margin="0" MinWidth="1000">

    <Window.Resources>       
        <Style x:Key="{x:Type Window}" TargetType="{x:Type Window}">
            <Setter Property="SnapsToDevicePixels" Value="true" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Window}">
                        <Grid>
                            <Grid.Background>
                                <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.WindowColorKey}}" />
                            </Grid.Background>
                            <AdornerDecorator>
                                <ContentPresenter />
                            </AdornerDecorator>
                            <ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="Collapsed" IsTabStop="false" />
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="ResizeMode" Value="CanResizeWithGrip">
                                <Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
       
        ...
    </Window.Resources>       
   
    <Grid>
    <StackPanel MinHeight="600" MinWidth="1000" HorizontalAlignment="Stretch" Margin="0" Orientation="Vertical"> 
            <StackPanel.Background>
                <RadialGradientBrush>
                    <GradientStop Color="#FF80B3A4" />
                    <GradientStop Color="#FF458AA4" Offset="1.1" />
                </RadialGradientBrush>
            </StackPanel.Background>

            <!-- HEADER SECTION -->
            <Grid> ... <Grid/>

            <!-- MAIN SECTION -->
            <Grid> ... <Grid/>   

            <!-- FOOTER SECTION -->
            <Grid> ... <Grid/>     
    
    </StackPanel>
    </Grid>
           
           

WPF.Themes dis-assembled for customization with Nuget & ClickOnce Deployments


// NOTE: CLASSES HAVE BEEN EXTRACTED FROM WPF.THEMES.DLL
// NOTE: FOR THE PURPOSE OF KEEPING THE SHINYBLUE THEME,
// NOTE: SINCE THE NUGET DLL WILL NOT ALLOW CODE SIGNING.
//
// NOTE: THIS CODE ATTEMPTS TO KEEP THE SAME OBJECT LOADING PROCESSES AS THE ORIGINAL DLL.
// NOTE: HOWEVER, SINCE THE THEME.XAML MUST BE LOADED INTO THE ACTUAL "RESOURCES" FILE,
// NOTE: AND WE HAVE ALREADY LOADED THE SHINYBLUE.XAML INTO THE APP VIA THE \Resources\DefaultStyles.xaml
// NOTE: WE HAVE SIMPLY ADDED THIS CODE, TO PROVIDE WPF THEME CUSTOMIZATION, IF NEEDED.
//
namespace myApp.MainForm.Themes
{
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Resources;

public static class ThemeManager
{
public static readonly DependencyProperty ThemeProperty = DependencyProperty.RegisterAttached("Theme", typeof(string), typeof(ThemeManager), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(ThemeManager.OnThemeChanged)));

public static void ApplyTheme(this Application app, string theme)
{
ResourceDictionary themeResourceDictionary = GetThemeResourceDictionary(theme);
if (themeResourceDictionary != null)
{
app.Resources.MergedDictionaries.Clear();
app.Resources.MergedDictionaries.Add(themeResourceDictionary);
}
}

public static void ApplyTheme(this FrameworkElement control, string theme)
{
ResourceDictionary themeResourceDictionary = GetThemeResourceDictionary(theme);
if (themeResourceDictionary != null)
{
control.Resources.MergedDictionaries.Clear();
control.Resources.MergedDictionaries.Add(themeResourceDictionary);
}
}

public static string GetTheme(DependencyObject d)
{
return (string)d.GetValue(ThemeProperty);
}

public static Uri GetResourceThemesUri(string theme)
{
Assembly assembly = Assembly.GetExecutingAssembly();
AssemblyName assemblyName = new AssemblyName(assembly.FullName);
var x = new Uri(String.Format(assemblyName.Name + @";component/Themes/{0}.xaml", theme), UriKind.Relative);
return x;
}


public static ResourceDictionary GetThemeResourceDictionary(string theme)
{
if (theme != null)
{
//KEEP: Assembly assembly = Assembly.LoadFrom("WPF.Themes.dll");
//KEEP: return (Application.LoadComponent(new Uri(string.Format("/WPF.Themes;component/{0}/Theme.xaml", theme), UriKind.Relative)) as ResourceDictionary);
//KEEP: Uri uri = new Uri(String.Format("myApp.MainForm;component/{0}/Theme.xaml", theme), UriKind.Relative);

StreamResourceInfo info = Application.GetResourceStream(GetResourceThemesUri(theme));
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
ResourceDictionary myResourceDictionary = (ResourceDictionary)reader.LoadAsync(info.Stream);
//KEEP: Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
return myResourceDictionary;
}
return null;
}

public static string[] GetThemes()
{
//return new string[] { "ExpressionDark", "ExpressionLight", "ShinyBlue", "ShinyRed", "DavesGlossyControls", "WhistlerBlue", "BureauBlack", "BureauBlue", "BubbleCreme", "TwilightBlue", "UXMusingsRed", "UXMusingsGreen", "UXMusingsBubblyBlue" };
return new string[] { "ShinyBlue" };
}

private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
string newValue = e.NewValue as string;
if (!String.IsNullOrEmpty(newValue))
{
ContentControl control = d as ContentControl;
if (control != null)
{
control.ApplyTheme(newValue);
}
}
}

public static void SetTheme(DependencyObject d, string value)
{
d.SetValue(ThemeProperty, value);
}
}
}

namespace myApp.MainForm.Themes.Properties
{
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.Resources;
using System.Runtime.CompilerServices;

[DebuggerNonUserCode, CompilerGenerated, GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
internal class Resources
{
private static CultureInfo resourceCulture;
private static System.Resources.ResourceManager resourceMan;

internal Resources()
{
}

[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}

[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager
{
get
{
if (object.ReferenceEquals(resourceMan, null))
{
System.Resources.ResourceManager manager = new System.Resources.ResourceManager("myApp.MainForm.Properties.Resources", typeof(Resources).Assembly);
resourceMan = manager;
}
return resourceMan;
}
}
}

[CompilerGenerated, GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed class Settings : ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings) SettingsBase.Synchronized(new Settings()));

public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

Unity BootStrapper utilizing Microsoft's Enterprise Library, Prism, and Nuget


// NOTE: Unity BootStrapper utilizing Microsoft's Enterprise Library Exception Handling & Prism via Nuget Libraries
// NOTE: The AuthenticateUser is required during loading, in this case, in order to load primary service interfaces

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using myApp.Desktop.Views;
using myApp.Infrastruct;
using myApp.Infrastruct.Interfaces;
using myApp.Infrastruct.Logging;
using myApp.Infrastruct.ModelObjects;
using myApp.Infrastruct.Services;
using myApp.Infrastruct.Session;

using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging;
using Microsoft.Practices.Prism.Logging;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.UnityExtensions;
using Microsoft.Practices.Unity;

namespace myApp.MainForm
{
public class Bootstrapper : UnityBootstrapper
{
//NOTE** CallbackLogger is used only for custom error handling during bootstrap loading
private readonly CallbackLogger m_callBackLogger = new CallbackLogger();

private static UserModel m_userMain;
public static UserModel UserMainObject
{
get
{
if (m_userMain != null)
{
return m_userMain;
}

var retValObject = new UserService().AuthenticateUser(Environment.UserDomainName, Environment.UserName);
if (retValObject.Success)
{
m_userMain = (UserModel)retValObject.Result;
}
return m_userMain;
}
set
{
m_userMain = value;
}
}

private static DataLookupModel m_dataLookupModel = new DataLookupModel(new ExceptionManager());
public static DataLookupModel DataLookupModelObject
{
get
{
return m_dataLookupModel;
}
set
{
m_dataLookupModel = value;
}
}

protected override DependencyObject CreateShell()
{
return Container.Resolve();
}

protected override void InitializeShell()
{
Application.Current.MainWindow = (ShellView) Shell;
Application.Current.MainWindow.Show();
}

public void ShowErrorWindow(string errorMsg)
{
Application.Current.MainWindow = new ErrorWindow(errorMsg);
Application.Current.MainWindow.Show();
}

protected override IModuleCatalog CreateModuleCatalog()
{
//NOTE** set the prism catalog directory to the root of the deployed executable
var moduleCatalog = new DirectoryModuleCatalog {ModulePath = @"."};
return moduleCatalog;
}

protected override ILoggerFacade CreateLogger()
{
return new EnterpriseLibraryLoggerAdapter();
}

protected override void ConfigureContainer()
{
//NOTE** Calling this first to log any unhandled errors during Bootstrapper load
Container.RegisterInstance(m_callBackLogger);

//NOTE** singleton objects
Container.RegisterInstance(UserMainObject);

Container.RegisterInstance(DataLookupModelObject);

//NOTE** SINGLETON CHECKING STATEMENT
//bool singleton = ReferenceEquals(Container.Resolve(), Container.Resolve());

Container.RegisterType();
Container.RegisterType();
Container.RegisterType();
Container.RegisterType();
Container.RegisterType(new InjectionConstructor());
Container.RegisterType();
Container.RegisterType();
Container.RegisterType();

//NOTE** Call Exception Handling Block after the log is created in the Prism Bootstrapper
BootstrapExceptionHandlingBlock();

//NOTE** Container is required to register variant Prism infrastructure services
base.ConfigureContainer();

//NOTE** TEST CASE FOR UNHANDLED EXCEPTION HERE using the CallbackLogger >>
// throw new Exception("TESTING BOOTSTRAPPER EXCEPTION");
}

protected override Microsoft.Practices.Prism.Regions.IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
var factory = base.ConfigureDefaultRegionBehaviors();
return factory;
}


private void BootstrapExceptionHandlingBlock()
{
Container.RegisterType(
new InjectionConstructor(new List
{
new ExceptionPolicyDefinition(ExceptionCategory.DEFAULT, ConfigureDefaultPolicy()),
new ExceptionPolicyDefinition(ExceptionCategory.DATA, ConfigureDataPolicy()),
new ExceptionPolicyDefinition(ExceptionCategory.SERVICE, ConfigureServicePolicy()),
new ExceptionPolicyDefinition(ExceptionCategory.UI, ConfigureUiPolicy())
})
);
}

private static IEnumerable ConfigureUiPolicy()
{
var uiPolicyObject = new List
{
new ExceptionPolicyEntry(
typeof (Exception),
PostHandlingAction.ThrowNewException,
new IExceptionHandler[]
{
new LoggingExceptionHandler(
"Error",
100,
TraceEventType.Error,
"UI Error",
0,
typeof (TextExceptionFormatter),
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer)
})
};

return uiPolicyObject;
}

private static IEnumerable ConfigureServicePolicy()
{
var servicePolicyObject = new List
{
new ExceptionPolicyEntry(
typeof (Exception),
PostHandlingAction.ThrowNewException,
new IExceptionHandler[]
{
new LoggingExceptionHandler(
"Error",
100,
TraceEventType.Error,
"Service Error",
0,
typeof (TextExceptionFormatter),
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer)
})
};

return servicePolicyObject;
}

private static IEnumerable ConfigureDefaultPolicy()
{
var dataPolicyObject = new List
{
new ExceptionPolicyEntry(
typeof (Exception),
PostHandlingAction.None,
new IExceptionHandler[]
{
new LoggingExceptionHandler(
"Error",
100,
TraceEventType.Error,
"Default Error",
0,
typeof (TextExceptionFormatter),
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer)
})
};

return dataPolicyObject;
}

private static IEnumerable ConfigureDataPolicy()
{
var dataPolicyObject = new List
{
new ExceptionPolicyEntry(
typeof (Exception),
PostHandlingAction.ThrowNewException,
new IExceptionHandler[]
{
new LoggingExceptionHandler(
"Critical",
100,
TraceEventType.Critical,
"Data Error",
0,
typeof (TextExceptionFormatter),
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer)
})
};

return dataPolicyObject;
}

public void ExitApplication()
{
Application.Current.Shutdown();
}
}
}