title: WPF MVVM Binding Window Icon to a property in view model
body: <p>I have a WPF MVVM application. In my project properties I have set the icon in "Application" tab.</p>
  
  <p>I am trying to unify the way the Window Icon is obtained from different places in my entire application. So I have created an extension method in a class:</p>
  
  <pre><code>internal static class IconUtilities
  {
      [DllImport("gdi32.dll", SetLastError = true)]
      private static extern bool DeleteObject(IntPtr hObject);
  
      public static ImageSource ToImageSource(this Icon icon)
      {
          Bitmap bitmap = icon.ToBitmap();
          IntPtr hBitmap = bitmap.GetHbitmap();
  
          ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(
              hBitmap,
              IntPtr.Zero,
              Int32Rect.Empty,
              BitmapSizeOptions.FromEmptyOptions());
  
          if (!DeleteObject(hBitmap))
          {
              throw new Win32Exception();
          }
  
          return wpfBitmap;
      }
  }
  </code></pre>
  
  <p>And a public property in my view model:</p>
  
  <pre><code>public Icon WindowIcon
  {
      get
      {
          return Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
      }
  }
  
  public ImageSource GetWindowIcon()
  {
      return WindowIcon.ToImageSource();
  }
  </code></pre>
  
  <p>so wherever I need to obtain the app icon in my view model I call this property to obtain it. So I ensure I am always using the same app icon.</p>
  
  <p>Now, I amb trying to bind this property to the window icon by doing this:</p>
  
  <pre><code>&lt;Window x:Name="MainWindow" x:Class="My.Apps.WPF.wMain"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit" 
      Icon="{Binding WindowIcon}"
  /&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>but in runtime the Window icon shown is the default, not that set in project properties. What am i doing wrong?</p>
  
  <p><strong>ATTEMPT #1</strong>:</p>
  
  <p>This was being called before InitializeComponents so I have moved into Window Loaded event.</p>
  
  <p>Now, from Window:</p>
  
  <pre><code>private void Window_Loaded(object sender, RoutedEventArgs e)
  {
      this.Icon = ((wMainViewModel)this.DataContext).WindowIcon;
  }
  </code></pre>
  
  <p>I get the error:</p>
  
  <pre><code>Cannot convert implicitly 'System.Drawing.Icon' type into 'System.Windows.Media.ImageSource'
  </code></pre>
  
  <p>So I try to do below:</p>
  
  <pre><code>private void Window_Loaded(object sender, RoutedEventArgs e)
  {
      this.Icon = ((wMainViewModel)this.DataContext).GetWindowIcon();
  }
  </code></pre>
  
  <p>And now I get the error:</p>
  
  <pre><code>ImageSource for Icon property should be an icon file.
  </code></pre>
  
  <p><strong>TESTING APP</strong>:</p>
  
  <hr>
  
  <h2>   SIMPLE WPF TESTING APPLICATION (NOT MVVM) - FOR TESTING PURPOSES ONLY</h2>
  
  <p>Below I write a complete WPF Application (NOT MVVM), taken from <a href="https://www.codeproject.com/Articles/38291/Implement-Splash-Screen-with-WPF" rel="nofollow noreferrer">here</a> and added some code. This sample code differs from all above posted: the purpose
  of this sample is to show the problem when assigning an ImageSource to a
  Window Icon. It has been tested in Visual Studio 2008 with NET Framework 3.5 and Visual Studio 2015 and NET Framework 3.5 as well. Both cases fails in SplashScreen code-behind constructor when setting this.Icon, see later in code below.</p>
  
  <p>Also the icon file (*.ico) used to test is: "C:\Program Files\Internet Explorer\images\bing.ico". This icon file has been added to my project and I have set build action as resource and not to copy to output directory as its properties.</p>
  
  <p>Also, in project properties, in application tab, I have select this icon (bing.ico) as the icon for the application. This icon will be extracted from code using below line:</p>
  
  <p>System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);</p>
  
  <p>See later in my code, just in SplashScreen code-behind, in the constructor.</p>
  
  <p><strong>Additional notes</strong>: I have Windows 8.1 Pro x64.</p>
  
  <p><strong>App.cs</strong> : </p>
  
  <pre><code>using System;
  using System.Drawing;
  using System.Reflection;
  using System.Threading;
  using System.Windows;
  
  namespace SplashDemo
  {
      class App: Application
      {
          [STAThread ( )]
          static void Main ( )
          { 
              Icon ico = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
              Splasher.Splash = new SplashScreen(ico);
              Splasher.ShowSplash();
  
              for ( int i = 0; i &lt; 5000; i++ )
              {                
                  DispatcherHelper.DoEvents();
                  Thread.Sleep ( 1 );
              }
  
              new App ( );
          }
  
          public App ( )
          {         
              StartupUri = new System.Uri ( "MainWindow.xaml", UriKind.Relative );
  
              Run ( );            
          }
      }
  }
  </code></pre>
  
  <p><strong>Notes</strong>: Icon object is of type System.Drawing.Icon</p>
  
  <p><strong>DispatcherHelper Class</strong> :</p>
  
  <pre><code>using System;
  using System.Security.Permissions;
  using System.Windows.Threading;
  
  namespace SplashDemo
  {
      public static class DispatcherHelper
      {
          /// &lt;summary&gt;
          /// Simulate Application.DoEvents function of &lt;see cref=" System.Windows.Forms.Application"/&gt; class.
          /// &lt;/summary&gt;
          [SecurityPermissionAttribute ( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode )]
          public static void DoEvents ( )
          {
              DispatcherFrame frame = new DispatcherFrame ( );
              Dispatcher.CurrentDispatcher.BeginInvoke ( DispatcherPriority.Background,
                  new DispatcherOperationCallback ( ExitFrames ), frame );
  
              try
              {
                  Dispatcher.PushFrame ( frame );
              }
              catch ( InvalidOperationException )
              {
              }
          }
  
          private static object ExitFrames ( object frame )
          {
              ( ( DispatcherFrame ) frame ).Continue = false;
  
              return null;
          }
      }
  }
  </code></pre>
  
  <p><strong>Splasher Class</strong> :</p>
  
  <pre><code>using System;
  using System.Windows;
  
  namespace SplashDemo
  {
      /// &lt;summary&gt;
      /// Helper to show or close given splash window
      /// &lt;/summary&gt;
      public static class Splasher
      {
          /// &lt;summary&gt;
          /// 
          /// &lt;/summary&gt;
          private static Window mSplash;
  
          /// &lt;summary&gt;
          /// Get or set the splash screen window
          /// &lt;/summary&gt;
          public static Window Splash
          {
              get
              {
                  return mSplash;
              }
              set
              {
                  mSplash = value;
              }
          }
  
          /// &lt;summary&gt;
          /// Show splash screen
          /// &lt;/summary&gt;
          public static void ShowSplash ( )
          {
              if ( mSplash != null )
              {
                  mSplash.Show ( );
              }
          }
          /// &lt;summary&gt;
          /// Close splash screen
          /// &lt;/summary&gt;
          public static void CloseSplash ( )
          {
              if ( mSplash != null )
              {
                  mSplash.Close ( );
  
                  if ( mSplash is IDisposable )
                      ( mSplash as IDisposable ).Dispose ( );
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>SplashScreen Class (Code-Behind)</strong> : </p>
  
  <pre><code>using System.Drawing;
  using System.Reflection;
  using System.Windows;
  using System.Windows.Interop;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  
  namespace SplashDemo
  {
      /// &lt;summary&gt;
      /// Interaction logic for SplashScreen.xaml
      /// &lt;/summary&gt;
      public partial class SplashScreen : Window
      {
          public SplashScreen ()
          {
              InitializeComponent();
          }
  
          public SplashScreen(Icon icon) : this()
          { 
              // BELOW LINE CRASHES
              this.Icon =  System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
          }
      }
  }
  </code></pre>
  
  <p><strong>Notes on SplashScreen class</strong>:</p>
  
  <ul>
  <li>If I use this.Icon =  System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); it throws below error in compilation time:</li>
  </ul>
  
  <blockquote>
    <p>cannot implicitly convert type 'system.drawing.icon' to
    'system.windows.media.imagesource'</p>
  </blockquote>
  
  <ul>
  <li>If I replace this line by this: this.Icon = icon.ToImageSource2();</li>
  </ul>
  
  <p>Then it throws a run-time error (not compilation error), a System.InvalidOperationException:</p>
  
  <blockquote>
    <p>ImageSource for Icon property must be an icon file</p>
  </blockquote>
  
  <p><strong>SplashScreen View</strong> : </p>
  
  <pre><code>&lt;Window 
      x:Class="SplashDemo.SplashScreen"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:SplashDemo" 
  
      Title="SplashScreen" Height="236" Width="414" WindowStartupLocation="CenterScreen" WindowStyle="None" 
      Background="Orange" BorderBrush="DarkOrange" BorderThickness="3" 
      ShowInTaskbar="False" ResizeMode="NoResize"&gt;
  
      &lt;Grid&gt;
          &lt;Grid.RowDefinitions&gt;            
              &lt;RowDefinition Height="2*" /&gt;
              &lt;RowDefinition Height="0.5*" /&gt;
          &lt;/Grid.RowDefinitions&gt;
  
          &lt;Label Grid.Row="0" Name="label1" FontSize="48" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="MintCream"&gt;
              &lt;Label.BitmapEffect&gt;
                  &lt;OuterGlowBitmapEffect GlowSize="15" /&gt;
              &lt;/Label.BitmapEffect&gt; Splash screen
          &lt;/Label&gt;
  
          &lt;Label Grid.Row="1" x:Name="CurrentTask" 
                 FontFamily="Microsoft Sans Serif" FontSize="18" FontStyle="Italic"  
                 Foreground="White" Content="Loading"&gt;
              &lt;Label.Style&gt;
                  &lt;Style TargetType="Label"&gt;
                      &lt;Style.Triggers&gt;
                          &lt;EventTrigger RoutedEvent="Label.Loaded"&gt;
                              &lt;EventTrigger.Actions&gt;
                                  &lt;BeginStoryboard&gt;
                                      &lt;Storyboard&gt;
                                          &lt;ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Content" Duration="00:00:00.8" RepeatBehavior="Forever"&gt;
                                              &lt;DiscreteObjectKeyFrame KeyTime="00:00:00.0" Value="Loading"/&gt;
                                              &lt;DiscreteObjectKeyFrame KeyTime="00:00:00.2" Value="Loading."/&gt;
                                              &lt;DiscreteObjectKeyFrame KeyTime="00:00:00.4" Value="Loading.."/&gt;
                                              &lt;DiscreteObjectKeyFrame KeyTime="00:00:00.6" Value="Loading..."/&gt;
                                          &lt;/ObjectAnimationUsingKeyFrames&gt;
                                      &lt;/Storyboard&gt;
                                  &lt;/BeginStoryboard&gt;
                              &lt;/EventTrigger.Actions&gt;
                          &lt;/EventTrigger&gt;
                      &lt;/Style.Triggers&gt;
                  &lt;/Style&gt;
              &lt;/Label.Style&gt;
          &lt;/Label&gt;
  
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p><strong>MainWindow View</strong> : </p>
  
  <pre><code>&lt;Window 
      x:Class="SplashDemo.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Main window" Height="332" Width="539" WindowStartupLocation="CenterScreen"&gt;
      &lt;Grid&gt;
          &lt;Label Margin="39,59,21,102" Name="label1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="36"&gt;Application window&lt;/Label&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p><strong>MainWindow Code-Behind</strong> : </p>
  
  <pre><code>using System.Windows;
  
  namespace SplashDemo
  {
      /// &lt;summary&gt;
      /// Interaction logic for Window1.xaml
      /// &lt;/summary&gt;
      public partial class MainWindow : Window
      {
          public MainWindow ( )
          {
              InitializeComponent ( );
          }
      }
  }
  </code></pre>
  
  <p><strong>IconUtilities Class (To convert from System.Drawing.Icon to System.Windows.Media.ImageSource)</strong> :</p>
  
  <pre><code>using System;
  using System.ComponentModel;
  using System.Drawing;
  using System.Runtime.InteropServices;
  using System.Windows;
  using System.Windows.Interop;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  
  namespace SplashDemo
  {
      internal static class IconUtilities
      {
          [DllImport("gdi32.dll", SetLastError = true)]
          private static extern bool DeleteObject(IntPtr hObject);
  
          public static ImageSource ToImageSource(this Icon icon)
          {
              Bitmap bitmap = icon.ToBitmap();
              IntPtr hBitmap = bitmap.GetHbitmap();
  
              ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(
                  hBitmap,
                  IntPtr.Zero,
                  Int32Rect.Empty,
                  BitmapSizeOptions.FromEmptyOptions());
  
              if (!DeleteObject(hBitmap))
              {
                  throw new Win32Exception();
              }
  
              return wpfBitmap;
          }
  
          // Below a simple method without extra objects:
          public static ImageSource ToImageSource2(this Icon icon)
          {
              ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
                                            icon.Handle,
                                            Int32Rect.Empty,
                                            BitmapSizeOptions.FromEmptyOptions());
  
              return imageSource;
          }
      }
  }
  </code></pre>
  
  <p><strong>Notes here</strong> : </p>
  
  <ul>
  <li>ImageSource is of type System.Windows.Media.ImageSource</li>
  <li>ToImageSource2 does the same as ToImageSource but without extra objects, see <a href="https://code.i-harness.com/en/q/122e2" rel="nofollow noreferrer">here</a>.</li>
  </ul>