Posted by: Zeeshan Amjad | May 15, 2013

ListBox in ComboBox


I came across a request to insert listbox inside the combobox. This particular task is quite simple and we already saw an example reverse of it here where we display combobox inside the listbox. The basic idea is same that is created an ObservableCollection of ObservableCollection and then set the ItemsSource property accordingly.

The second part of the question is little tricky. The second part of the question is to display the selected item of inner listbox in the combobox. We already solved similar problem where we have different presentation in combo box and selected item by using ItemContinerStyle property here. In that example we display multiple column in combo box but display only one data when we select the data. Now we are going to use the same technique here.

But here the problem is how can we get the selected item of listbox so we can display it in combo box.

Here we create an additional property in the class to store the selected item of the list box.

Code Snippet
public class State
{
    public string SelectedCity
    { get; set; }

    public ObservableCollection<string> Cities
    { get; set; }
}

 

We can get the selected item value by using SelectedItem property of listbox using data binding.

Code Snippet
<ListBox HorizontalContentAlignment="Stretch"
         SelectedItem="{Binding Path=SelectedCity}"
         ItemsSource="{Binding Cities}"/>

 

Rest is quite easy, we just display the selected city in the combo box.

Here is a complete C# code of the program.

Code Snippet
using System.Collections.ObjectModel;
using System.Windows;

namespace WpfComboList
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<State> States = new ObservableCollection<State>();

        public MainWindow()
        {
            InitializeComponent();

            ObservableCollection<string> maryland = new ObservableCollection<string>();

            maryland.Add("Frederick");
            maryland.Add("German Town");
            maryland.Add("Baltimore");
            maryland.Add("Annapolis");

            ObservableCollection<string> texas = new ObservableCollection<string>();

            texas.Add("Houston");
            texas.Add("Dallas");
            texas.Add("San Antonio");

            ObservableCollection<string> california = new ObservableCollection<string>();

            california.Add("Los Angeles");
            california.Add("Fremont");

            States.Add(new State() { Cities = maryland });
            States.Add(new State() { Cities = texas });
            States.Add(new State() { Cities = california });

            DataContext = States;
        }
    }
    
    public class State
    {
        public string SelectedCity
        { get; set; }

        public ObservableCollection<string> Cities
        { get; set; }
    }
}

 

And here is Complete XAML code of the program.

Code Snippet
<Window x:Class="WpfComboList.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="List In Combo" Height="350" Width="525">
    <Grid>
        <ComboBox HorizontalContentAlignment="Stretch" Height="35" Margin="5" ItemsSource="{Binding}">
            <ComboBox.ItemContainerStyle>
                <Style TargetType="{x:Type ComboBoxItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Border Margin="1" BorderBrush="Brown">
                                    <ListBox HorizontalContentAlignment="Stretch"
                                             SelectedItem="{Binding Path=SelectedCity}"
                                             ItemsSource="{Binding Cities}"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ComboBox.ItemContainerStyle>
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock VerticalAlignment="Center" Text="{Binding Path=SelectedCity}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</Window>

Here is an output of the program when we open the Combo box.

ListInCombo_1

And here is an output when we select something from the listbox.

ListInCombo_2

Posted by: Zeeshan Amjad | March 29, 2013

Switching to MVVM Part 2


We saw one example to see how can we move the existing project using MVVM here. But those are just the first steps in that direction not a complete solution. In any big project we are not using MVVM alone, but use it with other high level patterns. The most commonly used patterns are Command pattern, Mediator pattern and Event to Command pattern.

WPFPattern

It is better to have some reusable classes to implement some functionality. We have one implementation of ICommand interface here.

Code Snippet
using System;
using System.Windows.Input;

namespace WpfPattern
{
    public sealed class MyCommand<T1, T2> : ICommand
    {
        private Action _FunctionWithParam;
        private Action<T1> _Function;
        private Func<T2, bool> _Predicate;

        public MyCommand(Action functionWithoutParam)
        {
            _FunctionWithParam = functionWithoutParam;
        }

        public MyCommand(Action<T1> function)
        {
            _Function = function;
        }

        public MyCommand(Action functionWithoutParam, Func<T2, bool> predicate)
        {
            _FunctionWithParam = functionWithoutParam;
            _Predicate = predicate;
        }

        public MyCommand(Action<T1> function, Func<T2, bool> predicate)
        {
            _Function = function;
            _Predicate = predicate;
        }

        public void Execute(T1 parameter)
        {
            if (_Function != null)
            {
                _Function(parameter);
            }
        }

        public bool CanExecute(T2 parameter)
        {
            if (_Predicate != null)
            {
                return _Predicate(parameter);
            }

            return true;
        }

        #region Implement ICommand interface

        public bool CanExecute(object parameter)
        {
            return CanExecute((T2)parameter);
        }

        public void Execute(object parameter)
        {
            if (_FunctionWithParam != null)
            {
                _FunctionWithParam();
            }
            else
            {
                Execute((T1)parameter);
            }
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        #endregion
    }
}

Event to command pattern is define here. Here are two classes to implement this functionality.

Code Snippet
using System.Windows;
using System.Windows.Input;

namespace WpfPattern
{
    public sealed class EventBehavior
    {
        #region Fields

        private DependencyProperty property;
        private RoutedEvent routedEvent;

        #endregion

        #region Constructor

        public EventBehavior(RoutedEvent routedEvent)
        {
            this.routedEvent = routedEvent;
        }

        #endregion

        public void CallBack(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            UIElement element = obj as UIElement;

            property = args.Property;

            if (element != null)
            {
                if (args.OldValue != null)
                {
                    element.AddHandler(routedEvent, new RoutedEventHandler(EventHandler));
                }

                if (args.NewValue != null)
                {
                    element.AddHandler(routedEvent, new RoutedEventHandler(EventHandler));
                }
            }
        }

        private void EventHandler(object sender, RoutedEventArgs e)
        {
            DependencyObject obj = sender as DependencyObject;

            if (obj != null)
            {
                ICommand command = obj.GetValue(property) as ICommand;

                if (command != null)
                {
                    if (command.CanExecute(e))
                    {
                        command.Execute(e);
                    }
                }
            }
        }
    }
}

 

And here is one template factory class.

Code Snippet
using System.Windows;
using System.Windows.Input;

namespace WpfPattern
{
    public sealed class BehaviorFactory<T>
    {
        #region Private Constructor

        private BehaviorFactory()
        {

        }

        #endregion

        public static DependencyProperty CreateBehavior(string name, RoutedEvent routedEvent)
        {
            EventBehavior eb = new EventBehavior(routedEvent);

            DependencyProperty dp = DependencyProperty.RegisterAttached(name, typeof(ICommand), typeof(T),
                new PropertyMetadata(eb.CallBack));

            return dp;
        }

    }
}

 

Here is a mediator class defined here.

Code Snippet
using System;

namespace WpfPattern
{
    public class WeakReferenceWrapper
    {
        private WeakReference weakReference;

        public WeakReferenceWrapper(object receiever, Delegate action)
        {
            weakReference = new WeakReference(receiever);
            this.Action = action;
        }

        public Delegate Action
        { get; set; }
    }
}

 

And here is Mediator class.

Code Snippet
using System;
using System.Collections.Generic;

namespace WpfPattern
{
    public sealed class Mediator
    {
        private Dictionary<string, List<WeakReferenceWrapper>> actions =
             new Dictionary<string, List<WeakReferenceWrapper>>();

        public Mediator()
         {
         }

        public void Register<T>(string message, object receiever, Action<T> action)
         {
             if (message == null)
             {
                 throw new ArgumentNullException("message");
             }

            if (action == null)
             {
                 throw new ArgumentNullException("action");
             }

            lock (actions)
             {
                 if (!actions.ContainsKey(message))
                 {
                     actions[message] = new List<WeakReferenceWrapper>();
                 }

                actions[message].Add(new WeakReferenceWrapper(receiever, action));
             }
         }

        public void UnRegister<T>(string message, object receiever, Action<T> action)
         {
             if (message == null)
             {
                 throw new ArgumentNullException("message");
             }

            if (action == null)
             {
                 throw new ArgumentNullException("action");
             }

            lock (actions)
             {
                 if (actions.ContainsKey(message))
                 {
                     List<WeakReferenceWrapper> actionlist = actions[message];

                    actionlist.Remove(new WeakReferenceWrapper(receiever, action));

                    if (actionlist.Count == 0)
                     {
                         actions.Remove(message);
                     }
                 }
             }
         }

        public void Send<T>(string message, T param)
         {
             if (message == null)
             {
                 throw new ArgumentNullException("message");
             }

            lock (actions)
             {
                 if (actions.ContainsKey(message))
                 {
                     List<WeakReferenceWrapper> actionslist = actions[message];

                    foreach (var action in actionslist)
                     {
                         action.Action.DynamicInvoke(param);
                     }
                 }
             }
         }
    }
}

 

Similarly we defined the ViewModel based class here to reuse some common functionality. Here is our ViewModelBase class.

Code Snippet
using System;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfPattern
{
    public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
    {
        private bool _disposed;
        public event EventHandler RequestClose;

        public ICommand ExitCommand
        { get; set; }

        #region Constructor

        public ViewModelBase()
        {
            _disposed = false;
        }

        #endregion

        public void Close()
        {
            EventHandler handler = this.RequestClose;

            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        #region NotifyPropertyChanged Methods

        public void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Disposable Methods

        public void Dispose()
        {
            Dispose(true);

            // Use SupressFinalize in case a subclass
            // of this type implements a finalizer.
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    // Dispose Managed Resource
                }

                // Dispose Unmanaged Resources

                _disposed = true;
            }
        }

        #endregion
    }
}

 

As we noticed from the above examples that these high level patterns internally uses further primitive patterns. For example, MVVM uses Command, Disposable and Notification pattern, Event to command uses Factory pattern and Mediator uses factory pattern. Here is a diagram to represent this relationship.

WPFPattern2

Here we assumed that we are creating a simple MVVM based WPF application. In more advanced scenarios which as when one view model may contain other view model, we may use composite pattern, in case of complex interaction between some utility classes, we may uses façade and in case of handling different interface we may select adaptor pattern.

Posted by: Zeeshan Amjad | November 28, 2012

Named PART idiom


We already saw an example of using PART_ template here and here. Now the question is if we want to use PART_ in our control then how can we do it.

Let’s first create a custom control. The whole point is to override OnApplyTemplate method. In this method we will check the PART name and then take appropriate action on it. Here is our simple example of OnApplyTemplate where we just change the foreground and background color of the control.

Code Snippet
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    if (this.Template != null)
    {
        Control c = this.Template.FindName("PART_MyPart", this) as Control;

        if (c != null)
        {
            c.Background = Brushes.Blue;
            c.Foreground = Brushes.Yellow;
        }
    }
}

 

We also TemplatePart attribute to document this name.

Code Snippet
[TemplatePart(Name = "PART_MyPart", Type = typeof(Control))]
public class MyCustomControl : Control

 

Here is a complete code of our custom control.

Code Snippet
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfNamedPart
{
    [TemplatePart(Name = "PART_MyPart", Type = typeof(Control))]
    public class MyCustomControl : Control
    {
        static MyCustomControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (this.Template != null)
            {
                Control c = this.Template.FindName("PART_MyPart", this) as Control;

                if (c != null)
                {
                    c.Background = Brushes.Blue;
                    c.Foreground = Brushes.Yellow;
                }
            }
        }
    }
}

 

Now let’s use this custom control. In main window we are going to create two custom controls in stack panel. One defined the named part and the other doesn’t. Here is XAML of our main window.

Code Snippet
<Window x:Class="WpfNamedPart.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:WpfNamedPart"
        Title="Named Part Demo" Height="300" Width="400">
    <StackPanel>
        <local:MyCustomControl Margin="5">
            <local:MyCustomControl.Template>
                <ControlTemplate>
                    <Grid>
                        <Button x:Name="PART_MyPart" Width="150" Height="35" Content="Named Part defined"/>
                    </Grid>
                </ControlTemplate>
            </local:MyCustomControl.Template>
        </local:MyCustomControl>
        <local:MyCustomControl Margin="5">
            <local:MyCustomControl.Template>
                <ControlTemplate>
                    <Grid>
                        <Button Width="150" Height="35" Content="Named Part not defined"/>
                    </Grid>
                </ControlTemplate>
            </local:MyCustomControl.Template>
        </local:MyCustomControl>
    </StackPanel>
</Window>

 

Here is the output of this program.

NamedPartDemo

The output of the program clearly shows that template would apply if we specify the correct name of the control in control template.

Now there is a question, why not do the same thing in User control. We can define the same method in our user control class.

Code Snippet
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfNamedPart
{
    /// <summary>
    /// Interaction logic for MyUserControl.xaml
    /// </summary>
    [TemplatePart(Name = "PART_MyPart", Type = typeof(Control))]
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (this.Template != null)
            {
                Control c = this.Template.FindName("PART_MyPart", this) as Control;

                if (c != null)
                {
                    c.Background = Brushes.Blue;
                    c.Foreground = Brushes.Yellow;
                }
            }
        }
    }
}

 

But if we are going to use this control with named part then we will get an error message. Let’s add the user control in our stack panel in similar way we used the custom control.

Code Snippet
<local:MyUserControl>
    <local:MyUserControl.Template>
        <ControlTemplate>
            <Grid>
                <Button x:Name="PART_MyPart" Width="150" Height="35" Content="Named Part defined"/>
            </Grid>
        </ControlTemplate>
    </local:MyUserControl.Template>
</local:MyUserControl>

 

But this time we will get the compilation error.

error MC3093: Cannot set Name attribute value ‘PART_MyPart’ on element ‘Button’. ‘Button’ is under the scope of element ‘MyUserControl’, which already had a name registered when it was defined in another scope. Line 29 Position 33.

Posted by: Zeeshan Amjad | November 18, 2012

WinRT internals using C++. Part 3


We saw in the first part that there is a different object size when we are using ref keyword when creating class here. We can use one undocumented C++ command line switch “reportAllClassLayout” to see the class structure. We can type “/d1 reportAllClassLayout” at the “Additional Options” text box as shown in the screen shot.

WinRT_Internal_11

And let’s see what output is generated by this command line switch.

class MyClassB    size(24):
    +—
    | +— (base class __IMyClassBPublicNonVirtuals)
    | | +— (base class Object)
0    | | | {vfptr}
    | | +—
    | +—
    | +— (base class Object)
4    | | {vfptr}
    | +—
    | +— (base class IWeakReferenceSource)
    | | +— (base class __abi_IUnknown)
8    | | | {vfptr}
    | | +—
    | | +— (base class Object)
12    | | | {vfptr}
    | | +—
    | +—
16    | __abi_FTMWeakRefData __abi_reference_count
    +—

 

Let’s explore this output. The number at the left most shows the offset of the field. It means that the length of all the fields are 4 bytes except the last one which is 8 bytes as shown by this diagram. In addition to that we can even get the information about vtable just below of it. Here is the information about the vtable of this class.

MyClassB::$vftable@__IMyClassBPublicNonVirtuals@:
    | &MyClassB_meta
    |  0
0    | &MyClassB::__abi_QueryInterface
1    | &MyClassB::__abi_AddRef
2    | &MyClassB::__abi_Release
3    | &MyClassB::__abi_GetIids
4    | &MyClassB::__abi_GetRuntimeClassName
5    | &MyClassB::__abi_GetTrustLevel

MyClassB::$vftable@Object@:
    | -4
0    | &thunk: this-=4; goto MyClassB::__abi_QueryInterface
1    | &thunk: this-=4; goto MyClassB::__abi_AddRef
2    | &thunk: this-=4; goto MyClassB::__abi_Release
3    | &thunk: this-=4; goto MyClassB::__abi_GetIids
4    | &thunk: this-=4; goto MyClassB::__abi_GetRuntimeClassName
5    | &thunk: this-=4; goto MyClassB::__abi_GetTrustLevel

MyClassB::$vftable@__abi_IUnknown@:
    | -8
0    | &thunk: this-=8; goto MyClassB::__abi_QueryInterface
1    | &thunk: this-=8; goto MyClassB::__abi_AddRef
2    | &thunk: this-=8; goto MyClassB::__abi_Release
3    | &thunk: this-=8; goto MyClassB::__abi_Platform_Details_IWeakReferenceSource____abi_GetWeakReference
4    | &thunk: this-=8; goto MyClassB::GetWeakReference

MyClassB::$vftable@Object@IWeakReferenceSource@:
    | -12
0    | &thunk: this-=12; goto MyClassB::__abi_QueryInterface
1    | &thunk: this-=12; goto MyClassB::__abi_AddRef
2    | &thunk: this-=12; goto MyClassB::__abi_Release
3    | &thunk: this-=12; goto MyClassB::__abi_GetIids
4    | &thunk: this-=12; goto MyClassB::__abi_GetRuntimeClassName
5    | &thunk: this-=12; goto MyClassB::__abi_GetTrustLevel

MyClassB::__abi_QueryInterface this adjustor: 0
MyClassB::__abi_AddRef this adjustor: 0
MyClassB::__abi_Release this adjustor: 0
MyClassB::__abi_GetIids this adjustor: 0
MyClassB::__abi_GetRuntimeClassName this adjustor: 0
MyClassB::__abi_GetTrustLevel this adjustor: 0
MyClassB::GetWeakReference this adjustor: 0
MyClassB::__abi_Platform_Details_IWeakReferenceSource____abi_GetWeakReference this adjustor: 0

 

We can construct a following diagram with the help of vtable about the memory layout of the class.

WinRT_Internal_12

__abi_FTMWeakRefData is defined in vccorlib.h header file and it contains two pointers therefore it’s size is 8 bytes. Here is a class diagram of __abi_FTMWeakRefData.

WinRT_Internal_13

Here is a code of __abi_FTMWeakRefData from vccorlib.h

Code Snippet
// A class that represents a volatile refcount, that gets initialized to 0.
class __abi_FTMWeakRefData
{
    __abi_IUnknown* __weakRefSource;
    __abi_IUnknown* __pUnkMarshal;

public:
    __abi_FTMWeakRefData(::Platform::Object^ __targetArg)
    {
        auto __weakRef = ref new ::Platform::Details::WeakReferenceSource(__targetArg);
        __weakRefSource = reinterpret_cast<__abi_IUnknown*>(__weakRef);
        *reinterpret_cast<__abi_IUnknown**>(&__weakRef) = nullptr;

#if !defined(VCWINRT_DLL)
        long __hr = ::__Platform_CoCreateFreeThreadedMarshaler(__targetArg,  reinterpret_cast< ::Platform::Object^*>(&__pUnkMarshal));
#else
        long __hr = ::CoCreateFreeThreadedMarshaler(reinterpret_cast<IUnknown*>(__targetArg),  reinterpret_cast<IUnknown**>(&__pUnkMarshal));
#endif
        if (__hr != 0)
        {
            __weakRefSource->__abi_Release();
            __weakRefSource = nullptr;
        }
        __abi_ThrowIfFailed(__hr);
        
        if (__abi_module != nullptr)
        {
            __abi_module->__abi_IncrementObjectCount();
        }
    }

    __abi_FTMWeakRefData(::Platform::Object^ __targetArg, ::Platform::CallbackContext __contextArg)
    {
        auto __weakRef = ref new ::Platform::Details::WeakReferenceSource(__targetArg);
        __weakRefSource = reinterpret_cast<__abi_IUnknown*>(__weakRef);
        *reinterpret_cast<__abi_IUnknown**>(&__weakRef) = nullptr;

        if (__contextArg == ::Platform::CallbackContext::Any)
        {
#if !defined(VCWINRT_DLL)
            long __hr = ::__Platform_CoCreateFreeThreadedMarshaler(__targetArg,  reinterpret_cast< ::Platform::Object^*>(&__pUnkMarshal));
#else
            long __hr = ::CoCreateFreeThreadedMarshaler(reinterpret_cast<IUnknown*>(__targetArg),  reinterpret_cast<IUnknown**>(&__pUnkMarshal));
#endif
            if (__hr != 0)
            {
                __weakRefSource->__abi_Release();
                __weakRefSource = nullptr;
            }
            __abi_ThrowIfFailed(__hr);
        }

        if (__abi_module != nullptr)
        {
            __abi_module->__abi_IncrementObjectCount();
        }
    }

    // called for a partially created ref class i.e. exception thrown from ctor
    void __abi_dtor()
    {
        if (!__weakRefSource)
        {
            return;
        }

        __weakRefSource->__abi_Release();
        __weakRefSource = nullptr;

        if (__pUnkMarshal)
        {
            __pUnkMarshal->__abi_Release();
            __pUnkMarshal = nullptr;
        }
        
        if (__abi_module != nullptr)
        {
            __abi_module->__abi_DecrementObjectCount();
        }
    }

    inline unsigned long __stdcall Increment() volatile
    {
        if (!__weakRefSource)
        {
            return static_cast<unsigned long>(-1); // Called during destruction
        }

        return reinterpret_cast< ::Platform::Details::WeakReferenceSource^>(__weakRefSource)->IncrementStrongReference();
    }

    inline unsigned long __stdcall Decrement() volatile
    {
        if (!__weakRefSource)
        {
            return static_cast<unsigned long>(-1); // Called during destruction
        }

        unsigned long __refCount = reinterpret_cast< ::Platform::Details::WeakReferenceSource^>(__weakRefSource)->DecrementStrongReference();
        if (__refCount == 0)
        {
            __weakRefSource->__abi_Release();
            __weakRefSource = nullptr;

            if (__pUnkMarshal)
            {
                __pUnkMarshal->__abi_Release();
                __pUnkMarshal = nullptr;
            }

            // When destructing objects at the end of the program, we might be freeing
            // objects across dlls, and the dll this object is in might have already freed its module object.
            if (__abi_module != nullptr)
            {
                __abi_module->__abi_DecrementObjectCount();
            }
        }

        return __refCount;
    }

    inline __abi_IUnknown* GetFreeThreadedMarshaler()
    {
        return __pUnkMarshal;
    }

    inline ::Platform::Details::IWeakReference^ GetWeakReference()
    {
        return reinterpret_cast< ::Platform::Details::IWeakReference^>(__weakRefSource);
    }

    inline long __stdcall Get() volatile
    {
        return reinterpret_cast< ::Platform::Details::WeakReferenceSource^>(__weakRefSource)->GetRefcount();
    }
};

 

Here __abi_IUnknown is similar to IUnknown interface and the reason to define one more interface is defined in comment in vccorelib.h file where define this interface. Here is a code from the vccorlib.h header file.

Code Snippet
//
//// Don't want to define the real IUnknown from unknown.h here. That would means if the user has
//// any broken code that uses it, compile errors will take the form of e.g.:
////     predefined C++ WinRT types (compiler internal)(41) : see declaration of 'IUnknown::QueryInterface'
//// This is not helpful. If they use IUnknown, we still need to point them to the actual unknown.h so
//// that they can see the original definition.
////
//// For WinRT, we'll instead have a parallel COM interface hierarchy for basic interfaces starting with _.
//// The type mismatch is not an issue. COM passes types through GUID / void* combos – the original type
//// doesn't come into play unless the user static_casts an implementation type to one of these, but
//// the WinRT implementation types are hidden.
__interface __declspec(uuid("00000000-0000-0000-C000-000000000046")) __abi_IUnknown
{
public:
    virtual long __stdcall __abi_QueryInterface(::Platform::Guid&, void**) = 0;
    virtual unsigned long __stdcall __abi_AddRef() = 0;
    virtual unsigned long __stdcall __abi_Release() = 0;
};

Posted by: Zeeshan Amjad | November 11, 2012

WinRT internals using C++. Part 2


Let’s further explore the WinRT and continue the discussion we started here. We created a simple program to see the ref class and simple class to compile in .Net. Let’s try to compile the same program in WinRT. Select Windows Store App Support from the project setting.

WinRT_Internal_05

And type /ZW in the additional options text box when select the command line from C/C++

WinRT_Internal_06

And type the following program.

Code Snippet
class A
{
};

ref class B
{
};

int main()
{
    int s1 = sizeof(A);

    int s2 = sizeof(B);
}

 

Now when we compile it we will get one compilation error.

WinRT_Internal_07

This compilation error gives me some extra information i.e. name of one assembly required by the C++ program named platform.winmd. I searched this file on my computer and found it on multiple locations.

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcpackages

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.VCLibs\11.0\References\CommonConfiguration\neutral

Let’s try our old tool dumbin on this file. Type this at command prompt

dumpbin platform.winmd

Here is its output

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcpackages>dumpbin platfo
rm.winmd
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file platform.winmd

File Type: DLL

  Summary

        2000 .reloc
        2000 .rsrc
        6000 .text

 

It means that winmd file is simple Windows DLL as shown by the output of the program. But we couldn’t get any extra information from it. Let’s try to open the same file from ildasm to see if we can get some extra information. Idasm opens this file successfully and here is what we will get from ildasm.

WinRT_Internal_08

This shows that winmd file contains the meta data that is compatible with .Net meta data because we are able to open it in .Net tool (ildasm). Let’s explore it little bit more and see what we can find under the Platform namespace. In our previous post we came across Object class in Platform namespace, lets see the meta data of that class using ildasm.

Here is the meta data of Object class.

WinRT_Internal_09

But if we open any method then we couldn’t see any code because there is only meta data in winmd file no code.

WinRT_Internal_10

Posted by: Zeeshan Amjad | November 9, 2012

WinRT internals using C++. Part 1


Today I decided to play with WinRT using C++. I created a simple Blank Windows Store program and start looking at the source code generated by the Visual Studio. I discover that Visual Studio generate MainPage and App class as a ref class. Once I came across the ref classes when working on .Net using Managed C++ here is one example of it.

In my first experiment, I created two classes, one with the ref keyword and one without it.

Code Snippet
class MyClassA
{
};

ref class MyClassB
{
};

 

Then I used the sizeof operator to see how much memory is allocated for both of them.

Code Snippet
    int s1 = sizeof(MyClassA);

    int s2 = sizeof(MyClassB);

 

As expected the size of first one is 1 byte, but the size of second class is 24 bytes.

WinRT_Internal_01

It clearly shows that the second object must contain some extra information. I wanted to confirm the same thing with .Net, therefore I created one empty project in Visual Studio and set the property to use the common language runtime support i.e. /clr switch.

WinRT_Internal_02

And created exactly the same two classes. Here is our code.

Code Snippet
class A
{
};

ref class B
{
};

int main()
{
    int s1 = sizeof(A);

    int s2 = sizeof(B);
}

 

But I am not even able to compile the project. I am getting the following error message.

Error    1    error C2847: cannot apply sizeof to managed type ‘B’    C:\zamjad\Projects\WinRT\CppProject1\CppProject1\Source.cpp    14    1    CppProject1

It means that ref class in .Net and WinRT are two different things. Let’s go back to our WinRT program and play with it little bit more. Let’s generate the listing file of the source code.

WinRT_Internal_03

And then search for MyClassB to see what is special about this class. We will see the following entries in the file.

PUBLIC    ??0MyClassB@@Q$AAA@XZ                ; MyClassB::MyClassB
PUBLIC    ?__abi_QueryInterface@?QObject@Platform@@MyClassB@@U$AAGJAAVGuid@2@PAPAX@Z ; MyClassB::[Platform::Object]::__abi_QueryInterface
PUBLIC    ?__abi_AddRef@?QObject@Platform@@MyClassB@@U$AAGKXZ ; MyClassB::[Platform::Object]::__abi_AddRef
PUBLIC    ?__abi_Release@?QObject@Platform@@MyClassB@@U$AAGKXZ ; MyClassB::[Platform::Object]::__abi_Release
PUBLIC    ?__abi_GetIids@?QObject@Platform@@MyClassB@@U$AAGJPAKPAPAVGuid@2@@Z ; MyClassB::[Platform::Object]::__abi_GetIids
PUBLIC    ?__abi_GetRuntimeClassName@?QObject@Platform@@MyClassB@@U$AAGJPAPAUHSTRING__@@@Z ; MyClassB::[Platform::Object]::__abi_GetRuntimeClassName
PUBLIC    ?__abi_GetTrustLevel@?QObject@Platform@@MyClassB@@U$AAGJPAW4__abi_TrustLevel@@@Z ; MyClassB::[Platform::Object]::__abi_GetTrustLevel
PUBLIC    ?GetWeakReference@?QIWeakReferenceSource@Details@Platform@@MyClassB@@U$AAAP$AAUIWeakReference@23@XZ ; MyClassB::[Platform::Details::IWeakReferenceSource]::GetWeakReference
PUBLIC    ?__abi_Platform_Details_IWeakReferenceSource____abi_GetWeakReference@?QIWeakReferenceSource@Details@Platform@@MyClassB@@U$AAGJPAP$AAUIWeakReference@23@@Z ; MyClassB::[Platform::Details::IWeakReferenceSource]::__abi_Platform_Details_IWeakReferenceSource____abi_GetWeakReference

 

We can get some extra information with the help of this listing file. It shows the class named Object in Platform namespace and few familiar methods. First take a look at the size of the Object class.

Code Snippet
int s0 = sizeof(Platform::Object);

 

And its size is 4 bytes. Just like any class that implement one interface or has at least one virtual function. These methods are from three interfaces, IUnknown, IInspectable and IWeakReferenceSource.

It means that when we create ref class in WinRT, it is actually implanting these three interfaces. Here is class diagram of these interfaces.

 

WinRT_Internal_04

Posted by: Zeeshan Amjad | November 1, 2012

HorizontalContentAlignment in WPF and WinRT


When saw several usage of HorizontalContentAlignment property when we want to display more than one data in list box or combo box in WPF. Let’s first review this in WPF before studying in WinRT. HorizontalContentAlignment is an enum type of HorizontalAlignment with four possible values, as shown by this class diagram.

HorizontalAlignment

Let’s take a look at this usage in ListBox in WPF. Let’s make a simple state class and use it.

Code Snippet
public class State
{
    public string Name
    { get; set; }

    public string Abbrivation
    { get; set; }
}

 

Let’s define the data template for ListBox to user HorizontalContentAlignment property.

Code Snippet
<ListBox Margin="5" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Navy" Margin="3" BorderThickness="2" CornerRadius="3">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Margin="2" Text="{Binding Name}"/>
                    <TextBlock Grid.Column="1" Margin="2" Text="{Binding Abbrivation}"/>
                </Grid>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

 

Here is its output.

WPFHorizontalContentAlignment

Now let’s do the same thing in WinRT and uses the same thing with ListView in WinRT. Here is our first attempt.

Code Snippet
<ListView ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Navy" Margin="3" BorderThickness="2" CornerRadius="3">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Margin="2" Text="{Binding Name}"/>
                    <TextBlock Grid.Column="1" Margin="2" Text="{Binding Abbrivation}"/>
                </Grid>
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

 

Here is its output.

WinRTHorizontalContentAlignment_01

From the output of this program it is clear that the usage of HorizontalContentAlignment property is different in WPF and WinRT. In WinRT we have to define the HorizontalContentAlignment on ListViewItem control, not on ListView. Here is XAML code to define it.

Code Snippet
<Style x:Key="style" TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>

 

We have to use ItemContainerStyle property to set this style. Here complete XAML code of the program.

Code Snippet
<common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="ListView.BasicPage"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:local="using:ListView"
    xmlns:common="using:ListView.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable="d">

    <Page.Resources>

        <!– TODO: Delete this line if the key AppName is declared in App.xaml –>
        <x:String x:Key="AppName">WinRT HorizontalContentAlignment</x:String>
        
        <Style x:Key="style" TargetType="ListViewItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </Page.Resources>

    <!–
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    –>
    <Grid Style="{StaticResource LayoutRootStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!– Back button and page title –>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource AppName}" Style="{StaticResource PageHeaderTextStyle}"/>
        </Grid>

        <FlipView
            x:Name="flipView"
            AutomationProperties.AutomationId="MainFlipView"
            AutomationProperties.Name="Main View"
            TabIndex="1"
            Grid.Row="1"
            >
            
            <ListView ItemsSource="{Binding}" ItemContainerStyle="{StaticResource style}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Border BorderBrush="Navy" Margin="3" BorderThickness="2" CornerRadius="3">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition/>
                                    <ColumnDefinition/>
                                </Grid.ColumnDefinitions>
                                <TextBlock Grid.Column="0" Margin="2" Text="{Binding Name}"/>
                                <TextBlock Grid.Column="1" Margin="2" Text="{Binding Abbrivation}"/>
                            </Grid>
                        </Border>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </FlipView>
        
        <VisualStateManager.VisualStateGroups>

            <!– Visual states reflect the application's view state –>
            <VisualStateGroup x:Name="ApplicationViewStates">
                <VisualState x:Name="FullScreenLandscape"/>
                <VisualState x:Name="Filled"/>

                <!– The entire page respects the narrower 100-pixel margin convention for portrait –>
                <VisualState x:Name="FullScreenPortrait">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!– The back button and title have different styles when snapped –>
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</common:LayoutAwarePage>

 

Here is an output of this program.

WinRTHorizontalContentAlignment_02

Posted by: Zeeshan Amjad | October 30, 2012

ListView comparision in WPF and WinRT


If we are using C# and XAML to develop WPF and WinRT application, then at first attempt both looks very similar. But they are quite different, let’s take a look at the example of ListView. ListView control in WPF and WinRT are quite different. Let’s first explore the class hierarchy of both controls. Here is a class hierarchy of WinRT ListView control.

WinRTListView_Class_Hierarchy

And here is class hierarchy of ListView control in WPF.

WPFListView_Class_Hierarchy

We can immediately noticed few differences just by looking at both hierarchies. The first difference is DispatcherObject and Visual class missing from WinRT. The other important difference is in WPF ListView is inherited by ListBox class, however in WinRT it is inherited by ListViewBase class. Both class hierarchies implement different interfaces.

Now let’s take a look at class diagram of both classes. Here is a class diagram of WinRT ListView.

WinRTListView

And here is a class diagram of WPF ListView.

WPFListView

From the class diagram it is very clear that in WinRT ListView is just a child class of ListViewBase without adding any functionality. It is because ListViewBase class implement the ISemanticZoomInformation interface.

In WPF we can use the GridView to display multiple columns in ListView, but in WinRT there is no View property in ListView. Therefore we have to define the item template and define layout there. Here is a XAML code to do this in WinRT.

Code Snippet
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <ListView ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    
                    <TextBlock Grid.Column="0" Margin="2" Text="{Binding Name}"/>
                    <TextBlock Grid.Column="1" Margin="2" Text="{Binding Abbrivation}"/>
                    <TextBlock Grid.Column="2" Margin="2" Text="{Binding Capital}"/>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

 

Here is its output of this program.

WinRTListViewOutput

Posted by: Zeeshan Amjad | October 21, 2012

Define styles for AppBar buttons


We already saw the usage of few standard styles in AppBar button here. StandardStyles.xaml already defined lots of styles. Here is one example from the StandardStyles.xaml file.

Code Snippet
<Style x:Key="SettingsAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="SettingsAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Settings"/>
    <Setter Property="Content" Value=""/>
</Style>

 

But we how do I know the look and feel of this style. The easiest way to see this is open the Windows Character map and type Segoe UI Symbol from the Font combo box and here you will see all the symbols as shown in the screen shot.

CharacterMap

In same way we can define our own styles, just by looking at the character map. Here is one style we defined that is not present in StandardStyles.xaml file.

Code Snippet
<Style x:Key="WatchAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="WatchAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Watch"/>
    <Setter Property="Content" Value="⌚"/>
</Style>

 

Let’s see how it looks like when used in AppBar.

Code Snippet
<Page.BottomAppBar>
    <AppBar>
        <StackPanel Orientation="Horizontal">
            <Button Style="{StaticResource WatchAppBarButtonStyle}"/>
        </StackPanel>
    </AppBar>
</Page.BottomAppBar>

 

Here is the output of this program.

AppBarDemo_05

There is nothing specific to Segoe UI Symbol. We can define the style for any type of font. Here is one example to define style for another symbol which is not in Segoe UI Symbol.

Code Snippet
<Style x:Key="AllahAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="AllahAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Allah"/>
    <Setter Property="Content" Value="ﷲ"/>
</Style>

 

And here is its output.

AppBarDemo_06

Posted by: Zeeshan Amjad | October 19, 2012

Define the AppBar in WinRT application


Define the AppBar in WinRT application is very easy. We have to set the BottomAppBar property of Page class. Let’s first explore the AppBar class first. AppBar is a content control as shown by this class hierarchy diagram.

AppBarClassHierarchy

WPF programmer one noticeable difference here. And the difference is that UIElement is directly inherited by DependencyObject class not with Visual class as it is happening in WPF. It means that in WinRT whatever is display on the screen is UIElement class responsibility. App bar class just introduced two new dependency properties and two new virtual methods. Here is a class diagram of AppBar class.

AppBar

Its usage is very simple, just create the AppBar object and assigned it to BottomAppBar property. Let’s first explore the Page class. Page class is inherited by UserControl class. Here is class diagram of it.

Page

 

From the class diagram it is shown that we can not only display the BottomAppBar, but also display the TopAppBar. Let’s do it. Here is a simple code to just demonstrate the AppBar.

Code Snippet
<Page.TopAppBar>
    <AppBar>
        <Button Content="Top"/>
    </AppBar>
</Page.TopAppBar>
<Page.BottomAppBar>
    <AppBar>
        <Button Content="Bottom"/>
    </AppBar>
</Page.BottomAppBar>

 

Here is the output of this program.

AppBarDemo_01

But it doesn’t look good and not following the metro guidelines. Fortunately Visual Studio created a proper style for us in StandardStyle.xaml file. You can see all the standard style and use it. There are lots of styles commented out, so don’t forget to uncomment those before using it. Let’s use the style for AppBar button if there is any. Here is a style for AppBar button define in the StandardStyle.xaml file with name “AppBarButtonStyle”.

Code Snippet
    <Style x:Key="AppBarButtonStyle" TargetType="ButtonBase">
        <Setter Property="Foreground" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
        <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="AutomationProperties.ItemType" Value="App Bar Button"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ButtonBase">
                    <Grid x:Name="RootGrid" Width="100" Background="Transparent">
                        <StackPanel VerticalAlignment="Top" Margin="0,12,0,11">
                            <Grid Width="40" Height="40" Margin="0,0,0,5" HorizontalAlignment="Center">
                                <TextBlock x:Name="BackgroundGlyph" Text="" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0" Foreground="{StaticResource AppBarItemBackgroundThemeBrush}"/>
                                <TextBlock x:Name="OutlineGlyph" Text="" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0"/>
                                <ContentPresenter x:Name="Content" HorizontalAlignment="Center" Margin="-1,-1,0,0" VerticalAlignment="Center"/>
                            </Grid>
                            <TextBlock
                               x:Name="TextLabel"
                               Text="{TemplateBinding AutomationProperties.Name}"
                               Foreground="{StaticResource AppBarItemForegroundThemeBrush}"
                               Margin="0,0,2,0"
                               FontSize="12"
                               TextAlignment="Center"
                               Width="88"
                               MaxHeight="32"
                               TextTrimming="WordEllipsis"
                               Style="{StaticResource BasicTextStyle}"/>
                        </StackPanel>
                        <Rectangle
                               x:Name="FocusVisualWhite"
                               IsHitTestVisible="False"
                               Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
                               StrokeEndLineCap="Square"
                               StrokeDashArray="1,1"
                               Opacity="0"
                               StrokeDashOffset="1.5"/>
                        <Rectangle
                               x:Name="FocusVisualBlack"
                               IsHitTestVisible="False"
                               Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
                               StrokeEndLineCap="Square"
                               StrokeDashArray="1,1"
                               Opacity="0"
                               StrokeDashOffset="0.5"/>

                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ApplicationViewStates">
                                <VisualState x:Name="FullScreenLandscape"/>
                                <VisualState x:Name="Filled"/>
                                <VisualState x:Name="FullScreenPortrait">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Width">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="60"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Snapped">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Width">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="60"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="PointerOver">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPointerOverBackgroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPointerOverForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPressedForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused">
                                    <Storyboard>
                                        <DoubleAnimation
                                               Storyboard.TargetName="FocusVisualWhite"
                                               Storyboard.TargetProperty="Opacity"
                                               To="1"
                                               Duration="0"/>
                                        <DoubleAnimation
                                               Storyboard.TargetName="FocusVisualBlack"
                                               Storyboard.TargetProperty="Opacity"
                                               To="1"
                                               Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Unfocused" />
                                <VisualState x:Name="PointerFocused" />
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="CheckStates">
                                <VisualState x:Name="Checked">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="0" Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Opacity"/>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundCheckedGlyph" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPressedForegroundThemeBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Unchecked"/>
                                <VisualState x:Name="Indeterminate"/>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

 

Visual Studio did a lot of work for us. Let’s use this style. Here is our new code for AppBar.

Code Snippet
    <Page.TopAppBar>
        <AppBar>
            <Button Content="Top" Style="{StaticResource AppBarButtonStyle}"/>
        </AppBar>
    </Page.TopAppBar>
    <Page.BottomAppBar>
        <AppBar>
            <Button Content="Bottom" Style="{StaticResource AppBarButtonStyle}"/>
        </AppBar>
    </Page.BottomAppBar>

 

Here is a output of this program.

AppBarDemo_02

Better than previous attempt, but still not perfect. Specially word bottom can’t fit perfectly inside the button, and this is because we are still not following the UI guideline fully. For this Visual Studio generated lots of styles based on AppBarButtonStyle. Let’s use those, but first we have to uncomment those. Here is our new code.

Code Snippet
    <Page.TopAppBar>
        <AppBar>
            <Button Style="{StaticResource SkipBackAppBarButtonStyle}"/>
        </AppBar>
    </Page.TopAppBar>
    <Page.BottomAppBar>
        <AppBar>
            <Button Style="{StaticResource SkipAheadAppBarButtonStyle}"/>
        </AppBar>
    </Page.BottomAppBar>

 

Note that we even don’t define the Content property, because it is defined by Style. Here is the output of this program.

AppBarDemo_03

StandardStyles.xaml defines lots of styles and it is worth consuming time to explore these. We can even define layout in the AppBar to display more than one control and use Grid, StackPanel etc. Let’s see one example.

Code Snippet
    <Page.TopAppBar>
        <AppBar>
            <StackPanel Orientation="Horizontal">
                <Button Style="{StaticResource SkipBackAppBarButtonStyle}"/>
                <Button Style="{StaticResource SkipAheadAppBarButtonStyle}"/>
            </StackPanel>
        </AppBar>
    </Page.TopAppBar>
    <Page.BottomAppBar>
        <AppBar>
            <StackPanel Orientation="Horizontal">
                <Button Style="{StaticResource PlayAppBarButtonStyle}"/>
                <Button Style="{StaticResource PauseAppBarButtonStyle}"/>
                <Button Style="{StaticResource EditAppBarButtonStyle}"/>
                <Button Style="{StaticResource SaveAppBarButtonStyle}"/>
                <Button Style="{StaticResource DeleteAppBarButtonStyle}"/>
                <Button Style="{StaticResource DiscardAppBarButtonStyle}"/>
                <Button Style="{StaticResource RemoveAppBarButtonStyle}"/>
            </StackPanel>
        </AppBar>
    </Page.BottomAppBar>

 

Here is the output of this program.

AppBarDemo_04

Older Posts »

Categories

Follow

Get every new post delivered to your Inbox.

Join 489 other followers