<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://bloggingabout.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>User Experience Design : Interaction</title><link>http://bloggingabout.net/blogs/andries/archive/tags/Interaction/default.aspx</link><description>Tags: Interaction</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Storing and retrieving WPF RibbonWindow settings (including the usercustomizable QuickAccessToolbar)</title><link>http://bloggingabout.net/blogs/andries/archive/2011/05/17/storing-and-retrieving-wpf-ribbonwindow-settings-including-the-usercustomizable-quickaccesstoolbar.aspx</link><pubDate>Tue, 17 May 2011 16:42:31 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:486705</guid><dc:creator>Andries van der Meulen</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/andries/rsscomments.aspx?PostID=486705</wfw:commentRss><comments>http://bloggingabout.net/blogs/andries/archive/2011/05/17/storing-and-retrieving-wpf-ribbonwindow-settings-including-the-usercustomizable-quickaccesstoolbar.aspx#comments</comments><description>&lt;p&gt;When you’re creating a desktop application you&amp;#39;d probably want to store some user settings.    &lt;br /&gt;Especially when using the Ribbon inside your application, there are several things (like &lt;em&gt;RibbonIsMinimized&lt;/em&gt; and &lt;em&gt;ShowQuickAccessToolBarOnTop&lt;/em&gt;) that users can set and want to keep even if the application en closed and restarted.&lt;/p&gt;  &lt;p&gt;There are several ways to store these user settings, and you can find some methods if you search the internet. But the biggest challenge is to store and retrieve the Quick Access Toolbar content which the user can change.&lt;/p&gt;  &lt;h3&gt;Defining&lt;/h3&gt;  &lt;p&gt;First the storage of the settings. I use the application user properties which are set through the project settings.    &lt;br /&gt;We define the following settings:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;FirstRun&lt;/strong&gt; (bool) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WindowSize&lt;/strong&gt; (System.Windows.Size) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WindowLocation&lt;/strong&gt; (System.Windows.Point) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WindowState&lt;/strong&gt; (System.Windows.WindowState) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;RibbonIsMinimized&lt;/strong&gt; (bool) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;ShowQuickAccessToolbarOnTop&lt;/strong&gt; (bool) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;RibbonQuickAccessToolbar&lt;/strong&gt; (string) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://bloggingabout.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/andries.metablogapi/4705.ProjectSettings_5F00_76CC226F.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="ProjectSettings" border="0" alt="ProjectSettings" src="http://bloggingabout.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/andries.metablogapi/6038.ProjectSettings_5F00_thumb_5F00_4511051A.png" width="524" height="308" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you can’t find the right type inside the type combobox, just select [Browse…] to select it from available DLL’s. &lt;em&gt;Point&lt;/em&gt; and &lt;em&gt;Size&lt;/em&gt; are found in &lt;strong&gt;WindowsBase&lt;/strong&gt;, and &lt;em&gt;WindowState&lt;/em&gt; is in &lt;strong&gt;PresentationFramework&lt;/strong&gt;.&lt;/p&gt;  &lt;h3&gt;Storing&lt;/h3&gt;  &lt;p&gt;Next step is storing the settings. I leave the QuickAccessToolbar out for this moment. I’ll add it later.&lt;/p&gt;  &lt;p&gt;The storing is taking place in de code behind of the Shell, which is the main window of the current application. It is not mandatory to do this in the code behind, but for the moment it is the easiest.&lt;/p&gt;  &lt;p&gt;I store the settings when the window is closing.&lt;/p&gt;  &lt;pre class="brush: csharp; auto-links: false;"&gt;protected override void OnClosing(CancelEventArgs e)
{
    Properties.Settings.Default.FirstRun = false;
    Properties.Settings.Default.WindowSize = new Size(Width, Height);
    Properties.Settings.Default.WindowLocation = new Point(Left, Top);
    Properties.Settings.Default.WindowState = WindowState;
    Properties.Settings.Default.RibbonIsMinimized = RibbonMenu.IsMinimized;
    Properties.Settings.Default.ShowQuickAccessToolBarOnTop = RibbonMenu.ShowQuickAccessToolBarOnTop;
    Properties.Settings.Default.RibbonQuickAccessToolBar = XamlWriter.Save(buttons);

    Properties.Settings.Default.Save();

    base.OnClosing(e);
}&lt;/pre&gt;


&lt;p&gt;The RibbonMenu is referencing to the &lt;em&gt;&amp;lt;Ribbon x:Name=&amp;quot;RibbonMenu&amp;quot; &amp;gt; &lt;/em&gt;inside the Shell.XAML. 

  &lt;br /&gt;Width, Height, Left, Top and WindowState are properties of the WPF (Ribbon)Window.&lt;/p&gt;

&lt;h2&gt;Retrieving&lt;/h2&gt;

&lt;p&gt;And when the application is starting again, you just have to get these settings and set them back. The best moment to do this is in the OnInitialized of the Shell.&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;protected override void OnInitialized(EventArgs e)
{
    base.OnInitialized(e);

    if (!Properties.Settings.Default.FirstRun)
    {
        Width = Properties.Settings.Default.WindowSize.Width;
        Height = Properties.Settings.Default.WindowSize.Height;
        Left = Properties.Settings.Default.WindowLocation.X;
        Top = Properties.Settings.Default.WindowLocation.Y;
        WindowState = Properties.Settings.Default.WindowState;
        RibbonMenu.IsMinimized = Properties.Settings.Default.RibbonIsMinimized;
        RibbonMenu.ShowQuickAccessToolBarOnTop = Properties.Settings.Default.ShowQuickAccessToolBarOnTop;
    }
}&lt;/pre&gt;

&lt;p&gt;So far the easy part.&lt;/p&gt;

&lt;h3&gt;QuickAccessToolbar&lt;/h3&gt;

&lt;p&gt;Storing and retrieving the QuickAccessToolbar is a bit more complicated. Because this can’t just be serialized.&amp;#160; &lt;br /&gt;First I tried and used &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlwriter.aspx" target="_blank"&gt;XamlWriter&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader.aspx" target="_blank"&gt;XamlReader&lt;/a&gt; to try serialize the items inside the QuickAccessToolbar. Although storing it worked fine (it made a huge xml file), when trying to load the Xaml, I soon experienced the problem that the XamlWriter also serialized the bindings (with it’s content) i set on the command property. Unfortunately these bindings are DelegateCommands from Prism, which can’t be constructed through deserialization.&lt;/p&gt;

&lt;p&gt;The solution is a bit complex, but it works just fine. I created my own entities for storing and retrieving the items inside the QuickAccessToolbar.&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;[Serializable]
public class QuickAccessToolbarButtonCollection : List&amp;lt;QuickAccessToolbarButton&amp;gt; { }

[Serializable]
public class QuickAccessToolbarButton
{
    public ImageSource LargeImageSource { get; set; }
    public ImageSource SmallImageSource { get; set; }
    public string Label { get; set; }
    public object QuickAccessToolBarId { get; set; }
    public object ToolTip { get; set; }
    public string ToolTipDescription { get; set; }
    public string KeyTip { get; set; }
    public Binding CommandBinding { get; set; }
}&lt;/pre&gt;

&lt;p&gt;Off course you can add more properties if you’re setting more attributes on the RibbonButton. These properties were everything I’ve used.&lt;/p&gt;

&lt;p&gt;Next step is creating and storing the QuickAccessToolbar items.&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;#region Create the QuickAccessToolbarButtonCollection
QuickAccessToolbarButtonCollection buttons = new QuickAccessToolbarButtonCollection();

foreach (RibbonButton rButton in RibbonMenu.QuickAccessToolBar.Items)
{
    if (rButton.KeyTip != &amp;quot;S&amp;quot;) // Don&amp;#39;t include the savebutton!
    {
        QuickAccessToolbarButton qaButton = new QuickAccessToolbarButton()
        {
            Label = rButton.Label,
            KeyTip = rButton.KeyTip,
            LargeImageSource = rButton.LargeImageSource,
            SmallImageSource = rButton.SmallImageSource,
            ToolTip = rButton.ToolTip,
            ToolTipDescription = rButton.ToolTipDescription,
            QuickAccessToolBarId = rButton.QuickAccessToolBarId,
            CommandBinding = BindingOperations.GetBinding(rButton, RibbonButton.CommandProperty)
        };
        buttons.Add(qaButton);
    }
}
#endregion&lt;/pre&gt;

&lt;p&gt;And when the collection filled, I use the XamlWriter to set this data inside a user setting
  &lt;pre class="brush: csharp; auto-links: false;"&gt;Properties.Settings.Default.RibbonQuickAccessToolBar = XamlWriter.Save(buttons);&lt;/pre&gt;

  &lt;p&gt;The reason I’m not using a conventional XMLSerializer is because the XamlWriter can serialize bindings.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;Last step is to read the stored setting. For this I use the XamlReader to deserialize back to our custom entity.&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;#region Load the QuickAccessToolbarButtonCollection
if (!string.IsNullOrEmpty(Properties.Settings.Default.RibbonQuickAccessToolBar))
{
    QuickAccessToolbarButtonCollection buttons = null;
    using (StringReader stringReader = new StringReader(Properties.Settings.Default.RibbonQuickAccessToolBar))
    {
        XmlReader xmlReader = XmlReader.Create(stringReader);
        buttons = (QuickAccessToolbarButtonCollection)XamlReader.Load(xmlReader);
        xmlReader.Close();
    }

    if (buttons != null)
    {
        for (int i = RibbonMenu.QuickAccessToolBar.Items.Count - 1; i &amp;gt;= 0; i--)
        {
            RibbonButton button = (RibbonButton)RibbonMenu.QuickAccessToolBar.Items.GetItemAt(i);
            if (button.KeyTip != &amp;quot;S&amp;quot;) // Don&amp;#39;t delete the savebutton!
                RibbonMenu.QuickAccessToolBar.Items.RemoveAt(i);
        }

        foreach (QuickAccessToolbarButton qaButton in buttons)
        {
            RibbonButton rButton = new RibbonButton()
            {
                Label = qaButton.Label,
                KeyTip = qaButton.KeyTip,
                LargeImageSource = qaButton.LargeImageSource,
                SmallImageSource = qaButton.SmallImageSource,
                ToolTip = qaButton.ToolTip,
                ToolTipDescription = qaButton.ToolTipDescription,
                QuickAccessToolBarId = qaButton.QuickAccessToolBarId
            };
            if (qaButton.CommandBinding != null)
                SetBinding(RibbonButton.CommandProperty, qaButton.CommandBinding);

            RibbonMenu.QuickAccessToolBar.Items.Add(rButton);
        }
    }
}
#endregion&lt;/pre&gt;


&lt;p&gt;Check explicitly if the commandbinding are null, else you get exceptions when initializing the Shell.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Overview&lt;/h3&gt;

&lt;p&gt;Below the complete two methods.&lt;/p&gt;

&lt;pre class="brush: csharp; auto-links: false;"&gt;protected override void OnInitialized(EventArgs e)
{
    base.OnInitialized(e);

    if (!Properties.Settings.Default.FirstRun)
    {
        Width = Properties.Settings.Default.WindowSize.Width;
        Height = Properties.Settings.Default.WindowSize.Height;
        Left = Properties.Settings.Default.WindowLocation.X;
        Top = Properties.Settings.Default.WindowLocation.Y;
        WindowState = Properties.Settings.Default.WindowState;
        RibbonMenu.IsMinimized = Properties.Settings.Default.RibbonIsMinimized;
        RibbonMenu.ShowQuickAccessToolBarOnTop = Properties.Settings.Default.ShowQuickAccessToolBarOnTop;

        #region Load the QuickAccessToolbarButtonCollection
        if (!string.IsNullOrEmpty(Properties.Settings.Default.RibbonQuickAccessToolBar))
        {
            QuickAccessToolbarButtonCollection buttons = null;
            using (StringReader stringReader = new StringReader(Properties.Settings.Default.RibbonQuickAccessToolBar))
            {
                XmlReader xmlReader = XmlReader.Create(stringReader);
                buttons = (QuickAccessToolbarButtonCollection)XamlReader.Load(xmlReader);
                xmlReader.Close();
            }

            if (buttons != null)
            {
                for (int i = RibbonMenu.QuickAccessToolBar.Items.Count - 1; i &amp;gt;= 0; i--)
                {
                    RibbonButton button = (RibbonButton)RibbonMenu.QuickAccessToolBar.Items.GetItemAt(i);
                    if (button.KeyTip != &amp;quot;S&amp;quot;) // Don&amp;#39;t delete the savebutton!
                        RibbonMenu.QuickAccessToolBar.Items.RemoveAt(i);
                }

                foreach (QuickAccessToolbarButton qaButton in buttons)
                {
                    RibbonButton rButton = new RibbonButton()
                    {
                        Label = qaButton.Label,
                        KeyTip = qaButton.KeyTip,
                        LargeImageSource = qaButton.LargeImageSource,
                        SmallImageSource = qaButton.SmallImageSource,
                        ToolTip = qaButton.ToolTip,
                        ToolTipDescription = qaButton.ToolTipDescription,
                        QuickAccessToolBarId = qaButton.QuickAccessToolBarId
                    };
                    if (qaButton.CommandBinding != null)
                        SetBinding(RibbonButton.CommandProperty, qaButton.CommandBinding);

                    RibbonMenu.QuickAccessToolBar.Items.Add(rButton);
                }
            }
        }
        #endregion
    }
}

protected override void OnClosing(CancelEventArgs e)
{
    #region Create the QuickAccessToolbarButtonCollection
    QuickAccessToolbarButtonCollection buttons = new QuickAccessToolbarButtonCollection();

    foreach (RibbonButton rButton in RibbonMenu.QuickAccessToolBar.Items)
    {
        if (rButton.KeyTip != &amp;quot;S&amp;quot;) // Don&amp;#39;t include the savebutton!
        {
            QuickAccessToolbarButton qaButton = new QuickAccessToolbarButton()
            {
                Label = rButton.Label,
                KeyTip = rButton.KeyTip,
                LargeImageSource = rButton.LargeImageSource,
                SmallImageSource = rButton.SmallImageSource,
                ToolTip = rButton.ToolTip,
                ToolTipDescription = rButton.ToolTipDescription,
                QuickAccessToolBarId = rButton.QuickAccessToolBarId,
                CommandBinding = BindingOperations.GetBinding(rButton, RibbonButton.CommandProperty)
            };
            buttons.Add(qaButton);
        }
    }
    #endregion

    Properties.Settings.Default.FirstRun = false;
    Properties.Settings.Default.WindowSize = new Size(Width, Height);
    Properties.Settings.Default.WindowLocation = new Point(Left, Top);
    Properties.Settings.Default.WindowState = WindowState;
    Properties.Settings.Default.RibbonIsMinimized = RibbonMenu.IsMinimized;
    Properties.Settings.Default.ShowQuickAccessToolBarOnTop = RibbonMenu.ShowQuickAccessToolBarOnTop;
    Properties.Settings.Default.RibbonQuickAccessToolBar = XamlWriter.Save(buttons);

    Properties.Settings.Default.Save();

    base.OnClosing(e);
}&lt;/pre&gt;


&lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=486705" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/andries/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://bloggingabout.net/blogs/andries/archive/tags/Interaction/default.aspx">Interaction</category><category domain="http://bloggingabout.net/blogs/andries/archive/tags/WPF/default.aspx">WPF</category><category domain="http://bloggingabout.net/blogs/andries/archive/tags/QuickAccessToolbar/default.aspx">QuickAccessToolbar</category><category domain="http://bloggingabout.net/blogs/andries/archive/tags/Ribbon/default.aspx">Ribbon</category><category domain="http://bloggingabout.net/blogs/andries/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Gesture-Based Computing Uses $1 Lycra Gloves</title><link>http://bloggingabout.net/blogs/andries/archive/2010/06/03/gesture-based-computing-uses-1-lycra-gloves.aspx</link><pubDate>Thu, 03 Jun 2010 08:25:37 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:483452</guid><dc:creator>Andries van der Meulen</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/andries/rsscomments.aspx?PostID=483452</wfw:commentRss><comments>http://bloggingabout.net/blogs/andries/archive/2010/06/03/gesture-based-computing-uses-1-lycra-gloves.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bloggingabout.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/andries.metablogapi/8182.lycraglovescomputingmit1_5F00_4E7E378F.jpg"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="lycra-gloves-computing-mit[1]" border="0" alt="lycra-gloves-computing-mit[1]" src="http://bloggingabout.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/andries.metablogapi/6622.lycraglovescomputingmit1_5F00_thumb_5F00_1F4C4BF8.jpg" width="505" height="391" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Interacting with your computer by waving your hands may require just a pair of multicolored gloves and a webcam, say two researchers at MIT who have made a breakthrough in gesture-based computing that&amp;#39;s inexpensive and easy to use.&lt;/p&gt;  &lt;p&gt;Very, very cool!&lt;/p&gt;  &lt;p&gt;Read More at: &lt;a title="http://www.wired.com/gadgetlab/2010/05/gloves-gesture-computing/" href="http://www.wired.com/gadgetlab/2010/05/gloves-gesture-computing/"&gt;http://www.wired.com/gadgetlab/2010/05/gloves-gesture-computing/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=483452" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/andries/archive/tags/Interaction/default.aspx">Interaction</category></item></channel></rss>