IgorShare Thoughts and Ideas

Consulting and Training

Archive for the ‘WPF’ Category

Topmost Floating Status Window (with animation on mouse hover)

Posted by Igor Moochnick on 05/30/2011

Sometimes an app needs an indication of it’s activity to be visible to the user at all times. We already have one mechanism – a tray icon. It’s a well-known and a well-documented trick.

Recently more and more apps are starting to show their activity with the top-most floating windows that are sliding into the view when needed. I see a reason to, sometimes, use this trick but I passionately condemn the implementation where a user (me specifically) can’t move this window out of the way where it overlaps with other notifications or the apps that I’m working with (like Skype or WebEx screen sharing for example).

Below is a small WPF XAML sugar that can allow you to have such a floating window, but, please, make sure a user can drag it out of the way or choose (in the settings?) on what side of the screen he want’s this window to doc. If time permits, I’ll post this information later.

<Window x:Class="JiveHub.Windows.FloatWindow"
        Name="ThisFloatWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="FloatWindow" Height="70" Width="100" Top="-70" WindowStyle="None" Topmost="True" BorderThickness="0" AllowsTransparency="True" Background="Transparent">
    
    <Window.Resources>
        <Storyboard x:Key="EmergeWindow">
            <DoubleAnimation Storyboard.TargetName="ThisFloatWindow"
                                     Storyboard.TargetProperty="(Canvas.Top)" To="-20" Duration="0:0:1">
                <DoubleAnimation.EasingFunction>
                    <ElasticEase Oscillations="2" EasingMode="EaseOut" Springiness="3"/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
        <Storyboard x:Key="ShrinkWindow">
            <DoubleAnimation Storyboard.TargetName="ThisFloatWindow"
                                     Storyboard.TargetProperty="(Canvas.Top)" To="-50" Duration="0:0:1" BeginTime="0:0:2">
                <DoubleAnimation.EasingFunction>
                    <ElasticEase Oscillations="2" EasingMode="EaseOut" Springiness="3"/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </Window.Resources>

    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="ThisFloatWindow"
                                     Storyboard.TargetProperty="(Canvas.Top)" To="-50" Duration="0:0:1" >
                        <DoubleAnimation.EasingFunction>
                            <ElasticEase Oscillations="2" EasingMode="EaseOut" Springiness="3"/>
                        </DoubleAnimation.EasingFunction>
                    </DoubleAnimation>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Window.GotFocus">
            <BeginStoryboard Storyboard="{StaticResource EmergeWindow}">
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Window.MouseEnter">
            <BeginStoryboard Storyboard="{StaticResource EmergeWindow}">
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Window.LostFocus">
            <BeginStoryboard Storyboard="{StaticResource ShrinkWindow}">
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Window.MouseLeave">
            <BeginStoryboard Storyboard="{StaticResource ShrinkWindow}">
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    
    <Grid>
        <Border Background="Green" CornerRadius="0,0,5,5" />
    </Grid>
</Window>

Posted in Tutorials, WPF | Leave a Comment »

Tip: Showing a Main view as a tray app with Caliburn.Micro

Posted by Igor Moochnick on 03/31/2011

The trick here is to make sure that the main view doesn’t pop-up right away in a visible form. After creation and resolving all the binding rules – the main view should be in a Hidden form.

This can easily be achieved with customizing the WindowManager by sub-classing it and adding one extra method:

[Export]
public class CustomWindowManager : WindowManager
{
    public Window MainWindow(object rootModel, object context = null)
    {
        return CreateWindow(rootModel, false, context);
    }
}

As soon as you’ll have the new WindowManager – the logic for the root view creation in the Boostrapper should be adjusted accordingly:

protected override void DisplayRootView()
{
    var viewModel = IoC.Get<IShell>();

    var windowManager = IoC.Get<CustomWindowManager>();

    _mainWindow = windowManager.MainWindow(viewModel);
    _mainWindow.Hide();
}

Here is a simple ShellView that uses a WPF TrayIcon implementation from CodeProject:

<UserControl ...
             xmlns:tb="clr-namespace:Hardcodet.Wpf.TaskbarNotification;assembly=Hardcodet.Wpf.TaskbarNotification"
             xmlns:cal="http://www.caliburnproject.org"
             Visibility="Hidden">
    <Grid>
        <tb:TaskbarIcon
            Visibility="Visible"
            x:Name="MyNotifyIcon"
            IconSource="/Resources/Images/Bulb.ico"
            MenuActivation="LeftOrRightClick" PopupActivation="DoubleClick">
            <!-- Set a simple context menu  -->
            <tb:TaskbarIcon.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Exit" cal:Message.Attach="AppExit" />
                </ContextMenu>
            </tb:TaskbarIcon.ContextMenu>
        </tb:TaskbarIcon>
    </Grid>
</UserControl>

The View Model for this view is very straight forward:

[Export(typeof(IShell))]
public class ShellTrayViewModel : Screen, IShell
{
    public void AppExit()
    {
        Application.Current.Shutdown();
    }
}

That’s it.

Posted in .NET, C#, Caliburn, MVVM, WPF | 5 Comments »

Office Applications via Prism of Unity

Posted by Igor Moochnick on 03/19/2011

This article was submitted to the MSDN magazine for publication 2 years ago. It wasn’t published due to budget cuts in the magazine and my small disagreement with Glen Block on the way I’ve used the bootstrappers. Glen was busy this time with MEF and we didn’t have time to resolve our differences.

So, for what it worth, it’s a great article and helped me and my teams in a lot of ways.

Now you’ll be the judge of that if you’ll keep on reading.

This article discusses:

  • VSTO – Visual Studio Tools for Office system
  • Prism v2 – December 19 drop 8 – Composite Application Guidance for WPF and Silverlight
  • Unity Application Block 1.2 – October 2008 drop
  • WPF
  • Visual Studio 2008 Sp1
  • Introduction

    Adding integration with Office suite was always a sweet fruit that only the daring people were willing to touch. This is mostly due to a different development model that the Office suite demands – you have to specifically target your functionality to work with Office applications and develop it separately from your main application. Office integration is based on COM knowledge. At the beginning, it was hard to wrap your head around the Office COM object model, but, with the release of the VSTO (Microsoft Visual Studio Tools for Office System), it became much easier to develop the integration for the .NET applications. The use of VSTO PIA (Primary Interpol Assemblies) makes it easier but does not change the paradigm very much: it is still necessary to develop separate application components that integrate into the Office suite. Until today, it has been hard to reuse and integrate parts of a primary product with the Office suite. We need a way to create GUI applications that can be easily decomposed into separate parts and components, and re-hosted in different ways and configurations. In other words: we need a way to create composite GUI blocks that can be hosted by Office applications and Windows applications equally.

    Note that the biggest benefits of creating composite applications in general, and for Office suite in particular, are maintainability and testability. Your components can be developed separately from each other by distributed teams and tested outside of the Office applications while maintaining high quality levels of the code. This greatly reduces the complexity of the development process.

    The Office Suite applications are, by nature, composite ones. They consist of a lot of different parts and services that have to intercommunicate and coexist in a common environment. Let us take Outlook as an outstanding example. It consists from many different parts, like folder trees, explorers (folder views), inspectors (item views), ribbons, form regions, configuration tabs, etc. All of those components have to be loaded, initialized and composed in a certain way. And do not forget that, after they are loaded, they have to communicate with each other and change their views and representations in reaction to the changes in the state of their peers.

    Let us see a simplified workflow of what happens when we change an active folder in Outlook to another one:

  • A new folder is selected in a folder tree
  • Toolbar is updated to enable or disable actions that are allowed in the selected folder
  • An active Explorer clears its current items list and populates it with the list of items from the new selected folder
  • A first item in the list is automatically selected, which causes the explorer to:
  • Update the toolbar to reflect actions that can be applied to the selected item
  • Locate an appropriate inspector that knows how to render the selected item and render it in an adjoined pane (to the explorer)
  • Locate the appropriate form regions that are associated with the selected item, create appropriate custom task panes and render them
  • Note how complex the described workflow is, and adding your own functionality into it brings certain challenges.

    Outlook is not alone in this case – all the other applications from the Microsoft Office Suite, in their own different contexts, have similarly complex workflows. All of them have menu bars, ribbons tool bars, panes, regions, etc. This leads us to the question: is there a way to solve these different complexities in a common way? The answer is Yes!

    Recently released Prism (i.e. the Composite Application Guidelines for WPF) is a perfect candidate to untangle such a tight logic knot and help us create simple composite applications that can play nicely with the applications from the Office suite. It describes how we can create composite applications from modular blocks and assemble then however we need. Furthermore, this broadens the horizons of the hosting solutions. This article will take you step by step through the implementation of an application that can be executed equally as a standalone or as a hosted one. We will see how it can be hosted within an Office application as well.

    Read the rest of this entry »

    Posted in Composite Applications, Office API, Prism, Tutorials, Unity, VSTO, WPF | 2 Comments »

    Now I have ALL of the Microsoft developer certifications – long journey is over!!!

    Posted by Igor Moochnick on 09/09/2009

    Now I own the full deck of the Microsoft certifications and I can sit back and relax (beer is in order ;-). Unfortunately, in the startup world that I operate most of the time, it’s not very recognizable achievement, but it’s nice to put these logos on my presentation slide decks and, especially now, I have a very powerful bragging rights – I have ALL of the Microsoft developers certifications !!!

    It was a lengthy path and, I should add, a very confusing one. It wasn’t very obvious what certification is a prerequisite to which one and, I must add, I’ve made a couple of mistakes on the road until I’ve discovered a developer’s certification map by Jorgen Thelin that put everything in order and cleared all the confusions.

    ms-cert-path-mcpd_4[1]

    Posted in .NET, ADO.Net, ASP.NET, C#, Community, Thoughts, WCF, Workflows, WPF | 6 Comments »

    WPF: Extracting BitmapImage from an attached resource in referenced assembly/library

    Posted by Igor Moochnick on 01/07/2009

    It was not that simple to find out what is a reference to a linked resource within an assembly. The biggest problem was to nail down the exact pack path to a resource. It becomes simple if you know the name of a specific assembly, but, in real life, the names are changing pretty often.

    This is the solution to such a problem: find out what assembly your code is running in and then construct a pack path to it. Then update it with a relative resource path. Under “relative resource path” I mean the path to your resource relative to the project (.proj) file within the VS solution. For example: if you like to store your images under “ProjectFolder/Images” folder then the relative path to your resource will be  “Images/ImageName.png”.

    Don’t forget that in WPF a linked resource should have a Resource build action (not Embedded Resource) !!!

    Here is a procedure that does all the above and hides all the hustle:

    private BitmapImage GetImage(string resourcePath)
    {
        var image = new BitmapImage();
    
        string moduleName = this.GetType().Assembly.GetName().Name;
        string resourceLocation =
            string.Format("pack://application:,,,/{0};component/{1}", moduleName,
                          resourcePath);
    
        try
        {
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            image.UriSource = new Uri(resourceLocation);
            image.EndInit();
        }
        catch (Exception e)
        {
            System.Diagnostics.Trace.WriteLine(e.ToString());
        }
    
        return image;
    }
    

    Posted in WPF | 1 Comment »

    Prism (V2) RegionManager fails to recognize non-WPF applications

    Posted by Igor Moochnick on 01/05/2009

    In the recent change of Prism (V2), the way how the Region Manager detects that it’s running in a Design Mode or not, has been changed. This has ultimately broke all my Prism plug-ins that were hosted by non-WPF applications. One of the examples of hosts for such a plug-in, is an Office AddIn.

    It took me about 6 hours to track down this problem and, to my amazement, I’ve found the place where it broke:

    private static bool RegionManager::IsInDesignMode(DependencyObject element)
    {
        // Due to a known issue in Cider, GetIsInDesignMode attached property value is not enough to know if it's in design mode.
        return DesignerProperties.GetIsInDesignMode(element) || Application.Current == null
            || Application.Current.GetType() == typeof(Application);
    }

    The reason is that for the non-WPF application the Application.Current is NULL !!!

    The solution

    1. 1. Create an empty class that will inherit from System.Windows.Applicatoin. (Name doesn’t matter):
      public class MyApp : System.Windows.Application 	{ 	}

       

    2. At the point of entry to a plug-in execute the following code:
      if (System.Windows.Application.Current == null)
      {
          // create the Application object
          new MyApp();
      }

    This is it – now you have an Application.Current that is not null and it’s not equal to typeof(Application).

    If, by any chance, you’d like to merge your application resources – do the following:

     // merge in your application resources 
    System.Windows.Application.Current.Resources.MergedDictionaries.Add(
        System.Windows.Application.LoadComponent(
            new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml",
            UriKind.Relative)) as ResourceDictionary);  

    For more information check DR.WPF’s article (http://www.drwpf.com/blog/Home/tabid/36/EntryID/10/Default.aspx) that beautifully explains the reasons and workarounds for the problem, described above.

    Posted in Office API, Prism, VSTO, WPF | 6 Comments »

    File encodings matter when writing Pixel Shaders

    Posted by Igor Moochnick on 12/17/2008

    Phewww… It took me some time to realize why my Pixel Shaders were not compiling with FXC. And this is a nasty one. Are you ready?..  IT DOES MATTER WHAT ENCODING YOUR FX FILE IS !!!!

    Make sure to save your file with encoding: Western European (Windows) – Codepage 1252.

    Check out this article for step-by-step instructions: http://blog.pixelingene.com/?p=224

    Posted in Shaders, WPF | Leave a Comment »

    Where is my config file if my main module is not inside the executing folder?

    Posted by Igor Moochnick on 09/04/2008

    Some people ask me: “What if my bootstrapper is loaded by my application from a another (preconfigured) folder and my Prism/Unity config file located in the same (non-executing) folder? How do I load it?”

    It’s pretty simple. You need to take your executing assembly as the base and figure out the required path.

    var assembly = Assembly.GetExecutingAssembly();
    Uri uriPath = new Uri(assembly.CodeBase);
    string path = Path.Combine(Path.GetDirectoryName(uriPath.AbsolutePath), "myApp.config" );
    var configMap = new ExeConfigurationFileMap { ExeConfigFilename = path  };
    var configuration = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
    
    unitySection = (UnityConfigurationSection)configuration.GetSection("unity");
    
    modulesSection = (ModulesConfigurationSection)configuration.GetSection("modules");
    

    Posted in IOC/DI, Prism, Tutorials, Unity | Leave a Comment »

    Prism: File-configuration-driven bootstrapper

    Posted by Igor Moochnick on 09/04/2008

    If you’d like to extract all your application configuration into a config file, this is what you can do:

    1. Create a config file. I suggest that you use a different file name than the App.config

    2. Override ConfigureContainer method in your bootstrapper

    private UnityConfigurationSection unitySection;
    
    private void GetConfigurationSection()
    {
        if  (unitySection == null)
        {
            var configMap = new ExeConfigurationFileMap { ExeConfigFilename = "myApp.config" };
            var configuration = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
    
            unitySection = (UnityConfigurationSection)configuration.GetSection("unity");
        }
    }
    
    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
    
        GetConfigurationSection();
    
        try
        {
            unitySection.Containers["global"].Configure(Container);
        }
        catch (Exception e)
        {
            System.Diagnostics.Trace.WriteLine(e.ToString());
        }
    }
    

    3. Point the module enumerator to the same config file via ConfigurationStore

    protected override IModuleEnumerator GetModuleEnumerator()
    {
        string baseDir = AppDomain.CurrentDomain.BaseDirectory;
        var store = new ConfigurationStore(baseDir);
        return new ConfigurationModuleEnumerator(store);
    }
    

     

    All this is fun, but, in case you have more than one config file that contains a Modules section – the ConfigurationStore will stop reading them as soon as it’ll find a first one. It may be the file that you needed in a first place, but, as well, it may be some other file.

    Here is a simple workaround:

    private UnityConfigurationSection unitySection;
    private ModulesConfigurationSection modulesSection;
    
    private void GetConfigurationSections()
    {
        if ((unitySection == null) && (modulesSection == null))
        {
            var configMap = new ExeConfigurationFileMap { ExeConfigFilename = "myApp.config" };
            var configuration = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
    
            unitySection = (UnityConfigurationSection)configuration.GetSection("unity");
    
            modulesSection = (ModulesConfigurationSection)configuration.GetSection("modules");
        }
    }
    
    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
    
        GetConfigurationSections();
    
        try
        {
            unitySection.Containers["global"].Configure(Container);
        }
        catch (Exception e)
        {
            System.Diagnostics.Trace.WriteLine(e.ToString());
        }
    }
    
    protected override IModuleEnumerator GetModuleEnumerator()
    {
        GetConfigurationSections();
    
        return new ConfigurationModuleEnumerator(new MyConfigStore(modulesSection));
    }
    
    public class MyConfigStore : ConfigurationStore
    {
        public ModulesConfigurationSection Section { get; private set; }
    
        public MyConfigStore(ModulesConfigurationSection section)
        {
            Section = section;
        }
    
        public override ModulesConfigurationSection RetrieveModuleConfigurationSection()
        {
            return Section;
        }
    }
    

     

    As you can see, by a simple overload of the ConfigurationStore, you can return exactly the modules section that you need. Note that this section is pre-retrieved by the same function that retrieves the “unity” configuration section.

    Posted in IOC/DI, Prism, Tutorials, Unity, WPF | Leave a Comment »

    Hosted Prism (or how to host Prism in the old projects)

    Posted by Igor Moochnick on 09/02/2008

    Recently I’m playing a lot with Prism and Unity and was looking for a way to gradually bring Prism to the existing projects. If you have an existing GUI project and you’d like to start using Prism (without rewriting everything from scratch) stay with me – I’m going to show a way that worked for me.

    In order to work with Prism you need a “root” window, or, how they call it, a “shell” window. But what if you already have a window? There is a solution to that.

    First of all create a WPF user control that will become a “shell” window to Prism. The XAML rules for this control is not different from any other Prism “shell” window. Just the root element of it is a “UserControl” and not “Window”. Let’s call it “ShellContainer”.

    Then you need to attach this control to your existing application. But first you need to tell the Bootstrapper about it, but you don’t need to activate it:

       1: protected override DependencyObject CreateShell()
       2: {
       3:     return Container.Resolve<ShellContainer>();
       4: }

    If your project is Windows Forms-based, you’ll need to drop on your form an ElementHost control. This control is located on the toolbox in the WPF Interoperability group. This will allow you to host a WPF User control on you non-WPF form.

       1: // Get the ShellContainer from IOC
       2: IUnityContainer container = new UnityContainer();
       3: var shellElement = container.Resolve<myLib.ShellContainer>();
       4:
       5: // Attach the WPF control to the host
       6: hostControl.Child = shellElement;

    If you have a WPF form you can add this WPF User Control either manually.

       1: // Get ShellContainer from IOC
       2: IUnityContainer container = new UnityContainer();
       3: var shellElement = container.Resolve<myLib.ShellContainer>();
       4:
       5: // Add the ShellContainer UserControl to the main window
       6: this.mainGrid.Children.Add(shellElement);

    From this point on you are on a home run – just follow the rest of the Prism guidelines.

    TIP: I found it convenient to put the ShellContainer with the Bootstrapper in the same class library with the rest of the configuration logic. This allows a clean separation of the infrastructure from the rest of the logic of the Prism modules.

    Posted in C#, IOC/DI, Prism, Tutorials, WPF | 4 Comments »

     
    %d bloggers like this: