An MVVMresources.xaml example.

Published 10/30/2014 by Christian
Tags: , , ,

OK - a quick WPF/XAML/MVVM post. Mostly for my own benefit, so I can remember the syntax. This one about a MVVM resource file.

<ResourceDictionary x:Class="FooBar.MVVMResources"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:vm="clr-namespace:foo.ViewModel"
                    xmlns:vw="clr-namespace:foo.View"
                    xmlns:vm_common="clr-namespace:bar.ViewModel;assembly=BarAssembly"
                    xmlns:vw_common="clr-namespace:bar.View;assembly=BarAssembly">

    <DataTemplate DataType="{x:Type vm:fooViewModel}">
        <vw:fooView/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type vm_common:barViewModel}">
        <vw_common:barView/>
    </DataTemplate>
</ResourceDictionary>

 

As always, feel free to comment, or ask.


GIF animation in WPF

Published 10/30/2014 by Christian
Tags: , , ,

Due to the imperfect scaling ability of GIF images, these are deprecated in WPF.

A work around though can be found here:

https://code.msdn.microsoft.com/windowsdesktop/CSWPFAnimatedGIF-3029aeb9/sourcecode?fileId=26331&pathId=41660693

This is how the control looks like:

/****************************** Module Header ******************************\
Module Name:	AnimatedGIFControl.cs
Project:	    CSWPFAnimatedGIF
Copyright (c) Microsoft Corporation.

The CSWPFAnimatedGIF demonstrates how to implement 
an animated GIF image in WPF.

This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace Ellab.WPF.Utilities
{
    public class AnimatedGIFControl : System.Windows.Controls.Image
    {
        private Bitmap _bitmap; // Local bitmap member to cache image resource
        private BitmapSource _bitmapSource;
        public delegate void FrameUpdatedEventHandler();
            

        /// <summary>
        /// Delete local bitmap resource
        /// Reference: http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx
        /// </summary>
        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool DeleteObject(IntPtr hObject);

        /// <summary>
        /// Override the OnInitialized method
        /// </summary>
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            this.Loaded += new RoutedEventHandler(AnimatedGIFControl_Loaded);
            this.Unloaded += new RoutedEventHandler(AnimatedGIFControl_Unloaded);           
        }

        /// <summary>
        /// Load the embedded image for the Image.Source
        /// </summary>
       
        void AnimatedGIFControl_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                // Get GIF image from Resources
                if (Ellab.WPF.Properties.Resources.ProgressIndicator != null)
                {
                    _bitmap = Ellab.WPF.Properties.Resources.ProgressIndicator;
                    Width = _bitmap.Width;
                    Height = _bitmap.Height;

                    _bitmapSource = GetBitmapSource();
                    Source = _bitmapSource;

                    StartAnimate();
                }
            }
            catch (Exception ex) { Ellab.Debug.GlobalDebug.debugForm.WriteText(ex); }
        }

        /// <summary>
        /// Close the FileStream to unlock the GIF file
        /// </summary>
        private void AnimatedGIFControl_Unloaded(object sender, RoutedEventArgs e)
        {
            StopAnimate();
        }

        /// <summary>
        /// Start animation
        /// </summary>
        public void StartAnimate()
        {
            ImageAnimator.Animate(_bitmap, OnFrameChanged);
        }

        /// <summary>
        /// Stop animation
        /// </summary>
        public void StopAnimate()
        {
            ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
        }

        /// <summary>
        /// Event handler for the frame changed
        /// </summary>
        private void OnFrameChanged(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                   new FrameUpdatedEventHandler(FrameUpdatedCallback));
        }

        private void FrameUpdatedCallback()
        {
            ImageAnimator.UpdateFrames();

            if (_bitmapSource != null)
                _bitmapSource.Freeze();

            // Convert the bitmap to BitmapSource that can be display in WPF Visual Tree
            _bitmapSource = GetBitmapSource();
            Source = _bitmapSource;
            InvalidateVisual();
        }

        private BitmapSource GetBitmapSource()
        {
            IntPtr handle = IntPtr.Zero;                

            try
            {
                handle = _bitmap.GetHbitmap();
                _bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
                    handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            finally
            {
                if (handle != IntPtr.Zero)
                    DeleteObject(handle);
            }

            return _bitmapSource;
        }

    }
}

And the control can be used like this. First set the namespace:

xmlns:local="clr-namespace:Ellab.WPF.Utilities;assembly=Ellab.WPF"

Then use it like

<local:AnimatedGIFControl x:Name="GIFCtrl"/>

As always, feel free to comment, or ask.


Layers in XAML

Published 7/13/2013 by Christian
Tags: ,

This took me some time to figure out how to do. But as always, as soon as you figure it out, its actually quite simple.

I had two images I, in some cases, wanted to place on top of each other. It turns out, that if you put a given number objects into the same grid cell, they will be placed in layers.

<Grid>
	<Grid Grid.Column="0" Grid.Row="0"> 
		<Image Source="{Binding Path=Image}" />
	</Grid>
	<Grid Grid.Column="0" Grid.Row="0">
		<Image Source="{Binding Path=HoverImage}" />
	</Grid>
</Grid>

As always, feel free to comment, or ask.


XAML

Published 12/10/2012 by Christian in Code
Tags:

Doing a new Modern UI/Metro style UI to our application, recently I’ve been fortunate enough to begin working in WPF.
To get a quick overview of XAML, I found these IMO rather good tutorials:


http://www.youtube.com/watch?v=0qE5hyuU9hE&feature=g-hist


http://www.youtube.com/watch?v=qPDNgN2mEeA


As of yet, I haven’t had time to watch the rest in the series, but I would guess that, if one would need more explanation, it would be worth watching them.

 

As always, feel free to comment, or ask.