Windows Phone 7 Error Handling - BugSense

December 21, 2011 at 2:25 AMdsoltesz

Its always good practice to have proper error handling in your application and a way for users to report the errror.  Recently I learned of a new service called http://www.bugsense.com. BugSense is a library made for mobile developers. Get the context of the errors, track errors in specific app version or filter errors by device. There was Internet connectivity at the time of the crash? BugSense collects all the information the mobile developer needs and create reports for you to easliy be able to track and resolve application errors.  Using BugSense in your Windows Phone 7.x application is super easy and its FREE! Start with installing the BugSense library for Windows Phone. Use NuGet by typing “Install-Package BugSense.WP7” to NuGet Console or Search for BugSense using the NuGet Package Manager UI or download the BugSense-WP7-v0.9.zip unzip and add a reference to BugSense.dll in your Windows Phone Project.

Then, all you need to do is go inside you App.xaml.cs file and add the following code inside the constructor: Don't forget to use your Project API key you'll find in your dashboard!

public App()
{    
    BugSenseHandler.Instance.Init(this, "Your_API_Key");    
    // You app's code
}

 I have in corporated bugsense into my nightly prayer application and its working great!!!

 

Posted in: .NET | c# | Windows Phone 7

Tags: ,

Windows Phone 7 app - Nightly Prayer

November 23, 2011 at 7:03 PMdsoltesz

I recently created my first wp7 app http://www.windowsphone.com/en-US/apps/3ca7bb09-7710-4114-bb97-62d2657c7e95.  I did something simple just to see what it took to build an app and go through the market place app submission process.  I spent about a week creating this app.  That includes setting up a dev machine, creating database and admin app to manage data, web services that the phone can talk to and then building of the actual app.  This app was built using MVVM design pattern and this MVVM Framework I mentioned in this post http://www.dansoltesz.com/post/2011/11/14/Windows-Phone-7-MVVM-Framework.aspx

 

While this app is simple in nature, it uses several core features that any app would need.  It handles proper tombstoning, page navigation with nice transitions, communicates with external services, uses ad control with location services, context menu support, application button and menu databinding,splash startup screen, proper error handling and reporting, background services and live tile updates and several windows phone 7 tasks for emailing and sharing.

 

In order to have my app ready for the submission process, I used the new windows phone 7 market place test kit that was available with the mango sdk.  This proved priceless in helping to identify any potential issues before submitting the app to the market place.  The biggest issue I ran into is having a fast startup time.  Per the certification process your app has to have the main page visible within 5 seconds.  This seems pretty easy to do but when your initializing viewmodels, databinding UI, using Panorama view which supports multiple UI's, checking data connections and connection to services, 5 seconds goes by pretty quick.  My first test was well over 5 seconds so I started doing some refactoring, added in splash screen that enabled my real main page to get loaded properly and when all was said an done, the app launches ina  few seconds on average.

 

Please check out the app and let me know of any issues or improvements and if you would like any details of anything, just ask.

Posted in: .NET | c# | Windows Phone 7

Tags: , , , ,

windows phone 7 serialize object to isolated storage

November 16, 2011 at 11:41 PMdsoltesz

I have been working with windows phone 7 recently and i want to be able to serialize an object to xml to save into isolated storage.  Here is a Isolated storage helper that will allow you to do jus that.

public class IsolatedStorageHelper
    {
        public const string MyObjectFile = "myObject.xml";
        public static void WriteToXml<T>(T data, string path)
        {
            // Write to the Isolated Storage
            var xmlWriterSettings = new XmlWriterSettings { Indent = true };

            using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Create))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
                    {
                        serializer.Serialize(xmlWriter, data);
                    }
                }
            }
        }
        public static T ReadFromXml<T>(string path)
        {
            T data = default(T);
            try
            {
                using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var stream = myIsolatedStorage.OpenFile(path, FileMode.Open))
                    {
                        var serializer = new XmlSerializer(typeof(T));
                        data = (T)serializer.Deserialize(stream);
                    }
                }
            }
            catch
            {    //add some code here
            }
            return data;
        }


    }

To save your object call

IsolatedStorageHelper.WriteToXml(MyObject, IsolatedStorageHelper.MyObjectFile);

To fetch your object

var myObject = IsolatedStorageHelper.ReadFromXml<MyObject> (IsolatedStorageHelper.MyObjectFile);

Posted in: .NET | c# | silverlight | Windows Phone 7

Tags: , , ,

Windows Phone 7 MVVM Framework

November 14, 2011 at 7:04 PMdsoltesz

I have recently starting building a new windows phone 7 application and I was looking for a nice MVVM framework to use.  After reviewing several frameworks, I decided to go with UltraLight MVVM framework.  This is a great light weight framework for developing MVVM Silverlight applications with support for tombstoning on the Windows Phone 7.

UltraLight.mvvm provides a quick, easy and light way to add the following features to your Windows Phone 7 applications:

  • Commands
  • Command binding for buttons (with parameters)
  • Support for binding commands to application buttons / menu items on the application bar
  • Dialogs, both notification and confirmation
  • Messaging using the event aggregator publisher/subscriber model
  • Service location
  • Design-time friendly view models
  • Tombstone-friendly view models with control hooks for tombstone events
  • Decoupled navigation support from the view model
  • Decoupled visual state support from the view model
  • Back button interception on the view model
  • Notify property changed using expressions instead of magic strings
  • Dispatcher helper for UI thread access

Posted in: .NET | c# | silverlight | Windows Phone 7

Tags: , , ,

Deleting a parent entity and related child entities with RIA Services

September 22, 2011 at 12:31 AMdsoltesz

I created an extension that will allow you to traverse child entities easily so that you can remove each one from the parent.  Code is below.

 

public static class EntityExtensions { #region Static Methods (public) public static IEnumerable TraverseChildEntities ( this Entity parent, EntityContainer container ) { IEnumerable entityCollectionProperties = from p in parent.GetType( ).GetProperties( ) where p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition( ) == typeof ( EntityCollection<> ) select p; //// For every entity list, bind to the entity removed event foreach ( PropertyInfo property in entityCollectionProperties ) { var collectionType = property.PropertyType.GetGenericArguments()[0]; EntitySet set; if (!container.TryGetEntitySet(collectionType,out set)) { continue; } var entityCollection = ( IEnumerable )property.GetValue( parent, null ); foreach ( Entity entity in entityCollection ) { foreach ( Entity childEntity in entity.TraverseChildEntities(container ) ) { yield return childEntity; } yield return entity; } } } #endregion }

 With this extension in place now when I want to delete a parent entity and related child entities I can do somethig like this.

 

foreach (var child in new List(Parent.TraverseChildEntities(DomainContext.EntityContainer))) { DomainContext.EntityContainer.GetEntitySet(child.GetType()).Remove(child); } DomainContext.Parents.Remove(parent);

Posted in: c# | silverlight | wcf ria services

Tags: , ,

silverlight listbox autoscroll behavior

July 29, 2011 at 2:09 AMdsoltesz

Sometimes your list boxes can have a lot of items in them.  Even though you may order the list it still can be difficult for the user to find and item.  I like to give the user the abiltiy to search for an item in the listbox.  To keep this clean with MVVM, I created a behavior that can autoscroll for your via databinding.

 

Here is the behavior

 


/// <summary>
    /// Auto scroll listbox to item that is bound to the FoundItem property
    /// </summary>
    public class ListBoxItemAutoScrollBehavior : Behavior<ListBox>
    {
        #region Properties
        /// <summary>
        /// Item that is bound to listbox that you want to autoscroll to
        /// </summary>
        public object FoundItem
        {
            get { return GetValue(FoundItemProperty); }
            set { SetValue(FoundItemProperty, value); }
        }
 
        public static readonly DependencyProperty FoundItemProperty = DependencyProperty.Register("FoundItem"typeof(object), typeof(ListBoxItemAutoScrollBehavior), new PropertyMetadata(FoundItemChanged));
 
        private static void FoundItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ListBoxItemAutoScrollBehavior)d).AssociatedObject.ScrollIntoView(e.NewValue);
        }
        #endregion
    }

 

Make sure you add a reference to System.Windows.Interactivity.

 

To use the behavior I do something like this.

<ListBox ItemsSource="{Binding MyItems}"  DisplayMemberPath="ItemName"  SelectionMode="Multiple">
                        <i:Interaction.Behaviors>
                            <behaviors:ListBoxItemAutoScrollBehavior FoundItem="{Binding FoundItem}"/>
                        </i:Interaction.Behaviors>
                    </ListBox>
<TextBox Text="{Binding ItemToFind, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" BorderThickness="1" />

 

Now in your view model just define your properties to bind to.


public ObservableCollection<Item> MyItems
        {
            get { return _myItems; }
            set
            {
 
                if (_myItems == valuereturn;
                _myItems = value;
                OnPropertyChanged(() => MyItems);
            }
        }
 
        public string ItemToFind
        {
            get { return _itemToFind; }
            set
            {
                if (_itemToFind == valuereturn;
                _itemToFind = value;
                 FoundItem = MyItems.FirstOrDefault(o => o.ItemName.StartsWith(_itemToFind, StringComparison.CurrentCultureIgnoreCase));
                OnPropertyChanged(() => ItemToFind);
                OnPropertyChanged(() => FoundItem);
            }
        }
         public Item FoundItem { getset; }

 Now when the user types in something into the textbox, it will autoscroll to the item that is found

Posted in: behaviors | c# | silverlight

Tags: , ,

silverlight attach behavior in code

October 27, 2010 at 9:51 PMdsoltesz

I had a scenario where I needed to build part of the UI completely from Code and wanted to include a behavior as part of one of the UI controls.

Lets walk through and example of how to do this.

I want to create a WrapPanel that has the FluidMoveBehavior associated to the WrapPanel and applies the behavior to all its children.



var panel = new WrapPanel
{
   HorizontalAlignment = HorizontalAlignment.Left
};

var timeSpan = new TimeSpan(0, 0, 0, 0, 400);
var ease = new CubicEase
{
    EasingMode = EasingMode.EaseIn
};
var fluidMoveBehavior = new FluidMoveBehavior
{
    AppliesTo = FluidMoveScope.Children,
    Duration = new Duration(timeSpan),
    EaseX = ease,
    EaseY = ease
};

System.Windows.Interactivity.Interaction.GetBehaviors(panel).Add(fluidMoveBehavior);

 

Pretty easy, just make sure you add references to

  • System.Windows.Interactivity
  • Microsoft.Expression.Effects
  • Microsoft.Express.Interactions

Posted in: .NET | behaviors | c# | silverlight

Tags: , ,

Silverlight tabcontrol with scrollable tabItems

July 20, 2010 at 6:31 PMdsoltesz

I ran into an issue where I had more tab items than could fit within the desired width of my tab control.  Instead of all the tab items appearing on a single line, they would wrap and create a multiline affect which I did not want.  I wanted the user to be able to scroll through the tab items if needed.  I did some checking to see if someone had built or customized the silverlight toolkit to support this but I did not find anything, so I decided to create a custom tabcontrol with scrollable items.  Below is a picture of the default tab control and my custom scrollable tabcontrol.  Note: I have only modified the "Top" layout for the tabcontrol so if someone wants to use one of the other layouts, they will have to update accordingly.

 

Here is the code for the custom scrollable tab control.

file: ScrollableTab.xaml.cs


 [StyleTypedProperty(Property = "TabLeftButtonTopStyle", StyleTargetType = typeof(RepeatButton)),
     StyleTypedProperty(Property = "TabRightButtonTopStyle", StyleTargetType = typeof(RepeatButton)),
     TemplatePart(Name = "TabLeftButtonTop", Type = typeof(RepeatButton)),
	 TemplatePart(Name = "TabRightButtonTop", Type = typeof(RepeatButton)),
     TemplatePart(Name = "TabScrollViewerTop", Type = typeof(ScrollViewer)),
     TemplatePart(Name = "TabPanelTop", Type = typeof(TabPanel))]
    public class SlidingTabControl : System.Windows.Controls.TabControl
    {
		private RepeatButton tabLeftButton;
		private RepeatButton tabRightButton;
        private ScrollViewer tabScrollViewer;
        private TabPanel tabPanelTop;
        private double currentHorizontalOffset = 0;
        private double maxHorizontalOffset = 0;

        /// 
        /// Tab Top Left Button style
        /// 
        public static readonly DependencyProperty TabLeftButtonTopStyleProperty = DependencyProperty.Register(
            "TabLeftButtonTopStyle",
            typeof(Style),
            typeof(SlidingTabControl),
            new PropertyMetadata(null));

        /// 
        /// Tab Top Left Button style
        /// 
        public static readonly DependencyProperty TabRightButtonTopStyleProperty = DependencyProperty.Register(
            "TabRightButtonTopStyle",
            typeof(Style),
            typeof(SlidingTabControl),
            new PropertyMetadata(null));

        /// 
        /// Initializes a new instance of the  class.
        /// 
        public SlidingTabControl()
        {
            this.DefaultStyleKey = typeof(SlidingTabControl);
            this.SelectionChanged += new SelectionChangedEventHandler(SlidingTabControl_SelectionChanged);
        }

        /// 
        /// Gets or sets the Tab Top Left Button style.
        /// 
        /// The left button style style.
        [Description("Gets or sets the tab top left button style")]
        [Category("ScrollButton")]
        public Style TabLeftButtonTopStyle
        {
            get { return (Style)GetValue(TabLeftButtonTopStyleProperty); }
            set { SetValue(TabLeftButtonTopStyleProperty, value); }
        }

        /// 
        /// Gets or sets the Tab Top Right Button style.
        /// 
        /// The left button style style.
        [Description("Gets or sets the tab top right button style")]
        [Category("ScrollButton")]
        public Style TabRightButtonTopStyle
        {
            get { return (Style)GetValue(TabRightButtonTopStyleProperty); }
            set { SetValue(TabRightButtonTopStyleProperty, value); }
        }

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

            //remove old handlers
            if (null != this.tabLeftButton)
            {
                this.tabLeftButton.Click -= this.tabLeftButton_Click;
            }
            if (null != this.tabRightButton)
            {
                this.tabRightButton.Click -= this.tabRightButton_Click;
            }

            //add new handlers
            this.tabLeftButton = GetTemplateChild("TabLeftButtonTop") as RepeatButton;
            this.tabRightButton = GetTemplateChild("TabRightButtonTop") as RepeatButton;
            this.tabScrollViewer = GetTemplateChild("TabScrollViewerTop") as ScrollViewer;
            this.tabPanelTop = GetTemplateChild("TabPanelTop") as TabPanel;
            if (null != this.tabLeftButton)
            {
                this.tabLeftButton.Click += new RoutedEventHandler(tabLeftButton_Click);
            }
            if (null != this.tabRightButton)
            {
                this.tabRightButton.Click += new RoutedEventHandler(tabRightButton_Click);
            }

        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            var size = base.ArrangeOverride(finalSize);

            if (this.tabPanelTop != null && this.tabScrollViewer != null)
            {
                if (this.tabPanelTop.ActualWidth > this.tabScrollViewer.ActualWidth)
                {
                    maxHorizontalOffset = this.tabPanelTop.ActualWidth - this.tabScrollViewer.ActualWidth + 30;
                }
                SetScrollButtonVisibility();
            }

            return size;
        }
        private void SlidingTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SlidingTabControl tabControl = sender as SlidingTabControl;
            tabControl.Dispatcher.BeginInvoke(new Action(() => UpdateZIndex(sender as SlidingTabControl)));
        }
        private void tabRightButton_Click(object sender, RoutedEventArgs e)
        {
            if (null != this.tabScrollViewer && null != this.tabPanelTop)
            {
                currentHorizontalOffset = this.tabScrollViewer.HorizontalOffset + 25;
                if (currentHorizontalOffset > maxHorizontalOffset)
                    currentHorizontalOffset = maxHorizontalOffset;
                this.tabScrollViewer.ScrollToHorizontalOffset(currentHorizontalOffset);
                SetScrollButtonVisibility();
            }
        }
        private void tabLeftButton_Click(object sender, RoutedEventArgs e)
        {
            if (null != this.tabScrollViewer)
            {
                
                currentHorizontalOffset = this.tabScrollViewer.HorizontalOffset - 25;
                if (currentHorizontalOffset < 0)
                    currentHorizontalOffset = 0;
                
                this.tabScrollViewer.ScrollToHorizontalOffset(currentHorizontalOffset);
                SetScrollButtonVisibility();
            }
            
        }
        private void SetScrollButtonVisibility()
        {
            if (null != this.tabScrollViewer)
            {
                if (null != this.tabLeftButton)
                {
                    if (this.currentHorizontalOffset > 0)
                        this.tabLeftButton.Visibility = Visibility.Visible;
                    else
                        this.tabLeftButton.Visibility = Visibility.Collapsed;

                }
                if (null != this.tabRightButton)
                {
                    if (currentHorizontalOffset >= maxHorizontalOffset)
                    {
                        this.tabRightButton.Visibility = System.Windows.Visibility.Collapsed;
                    }
                    else
                    {
                        this.tabRightButton.Visibility = System.Windows.Visibility.Visible;
                    }
                }
            }
        }
        private void UpdateZIndex(SlidingTabControl tc)
        {
            if (tc != null)
            {
                foreach (TabItem tabItem in tc.Items)
                {
                    tabItem.SetValue(Canvas.ZIndexProperty, (tabItem == tc.SelectedItem ? tc.Items.Count : (tc.Items.Count - 1) - tc.Items.IndexOf(tabItem)));
                }
            }

        }

        
    }

 

file generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TabControl"
    xmlns:System_Windows_Controls_Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls"
    >

 

    <Style TargetType="local:SlidingTabControl">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                    <GradientStop Color="#FFFEFEFE" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFA3AEB9" Offset="0"/>
                    <GradientStop Color="#FF8399A9" Offset="0.375"/>
                    <GradientStop Color="#FF718597" Offset="0.375"/>
                    <GradientStop Color="#FF617584" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Padding" Value="5"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:SlidingTabControl">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualTop">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualBottom">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualLeft">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualRight">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Grid x:Name="TemplateTop" Visibility="Collapsed">
                         <Grid.ColumnDefinitions>
                          <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
       </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
       <RepeatButton Content="&lt;" x:Name="TabLeftButtonTop" Style="{TemplateBinding TabLeftButtonTopStyle}"/>
                            <ScrollViewer x:Name="TabScrollViewerTop" Grid.Column="1" IsTabStop="False" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Hidden" >
                         <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelTop" Margin="20,2,2,-1" Canvas.ZIndex="1"/>
       </ScrollViewer>
       <RepeatButton Content="&gt;" x:Name="TabRightButtonTop" Style="{TemplateBinding TabRightButtonTopStyle}" Grid.Column="2"/>
                         <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0,0,3,3" MinWidth="10" MinHeight="10" Grid.Row="1" Grid.ColumnSpan="3">
                          <ContentPresenter x:Name="ContentTop" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                         </Border>
                         <Border x:Name="DisabledVisualTop" Background="#8CFFFFFF" CornerRadius="0,0,3,3" IsHitTestVisible="False" Opacity="0" Grid.Row="1" Grid.RowSpan="2" Canvas.ZIndex="1"/>
                        </Grid>
                        <Grid x:Name="TemplateBottom" Visibility="Collapsed">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelBottom" Margin="2,-1,2,2" Grid.Row="1" Canvas.ZIndex="1"/>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3,3,0,0" MinWidth="10" MinHeight="10">
                                <ContentPresenter x:Name="ContentBottom" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                            </Border>
                            <Border x:Name="DisabledVisualBottom" Background="#8CFFFFFF" CornerRadius="3,3,0,0" IsHitTestVisible="False" Opacity="0" Canvas.ZIndex="1"/>
                        </Grid>
                        <Grid x:Name="TemplateLeft" Visibility="Collapsed">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelLeft" Margin="2,2,-1,2" Canvas.ZIndex="1"/>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" CornerRadius="0,3,3,0" MinWidth="10" MinHeight="10">
                                <ContentPresenter x:Name="ContentLeft" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                            </Border>
                            <Border x:Name="DisabledVisualLeft" Background="#8CFFFFFF" Grid.Column="1" CornerRadius="0,3,3,0" IsHitTestVisible="False" Opacity="0" Canvas.ZIndex="1"/>
                        </Grid>
                        <Grid x:Name="TemplateRight" Visibility="Collapsed">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <System_Windows_Controls_Primitives:TabPanel x:Name="TabPanelRight" Grid.Column="1" Margin="-1,2,2,2" Canvas.ZIndex="1"/>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3,0,0,3" MinWidth="10" MinHeight="10">
                                <ContentPresenter x:Name="ContentRight" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
                            </Border>
                            <Border x:Name="DisabledVisualRight" Background="#8CFFFFFF" CornerRadius="3,0,0,3" IsHitTestVisible="False" Margin="0" Opacity="0" Canvas.ZIndex="1"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

  
</ResourceDictionary>

 

Download code

SlidingTabControlDemo.zip (2.10 mb)

Posted in: c# | wcf ria services

Tags: ,

silverlight save settings

April 6, 2010 at 6:19 PMdsoltesz

There are lots of time when you want to be able to store user settings in between sessions of your application. I found that using Isoloated Storage makes this very easy. I created a helper class to do just this.


IsolatedStorageManager.cs

using System.IO.IsolatedStorage;

namespace MyApp.Utilities

{

    public static class IsolatedStorageManager

    {

        /// <summary>

        /// Save property and value into isolated storage

        /// </summary>

        /// <param name="value">value to store</param>

        /// <param name="name">name of property</param>

        public static void SaveIntoIsolatedStorage(object value, string name)

        {

            IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings; 

            //If settings have never been saved, then we have to add appsetting first

            if (!appSettings.Contains(name))

            {

                appSettings.Add(name, null);

            }

            //store page user is currently on for when they come back in

            appSettings[name] = value;

        }

        public static bool Contains(string name)

        {

            IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;

            return appSettings.Contains(name);

        }

        /// <summary>

        /// Remove property value from isolated storage

        /// </summary>

        /// <param name="name">name of property</param>

        public static void Remove(string name)

        {

            IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;


            //If settings have been saved, then we remove since the user wants to select a new queue/page

            if (appSettings.Contains(name))

            {

                appSettings.Remove(name);

            }

        }

        /// <summary>

        /// Removes all properties stored in isolated storage

        /// </summary>

        public static void RemoveAll()

        {

            IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;

            appSettings.Clear();

        } 

        /// <summary>

        /// Retrieve setting that was stored in Isolated Storage

        /// </summary>

        /// <param name="name">name of the property to retrieve</param>

        /// <returns></returns>

        public static object LoadFromIsolatedStorage(string name)

        {

            IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;

            if (appSettings.Contains(name))

            {

                return appSettings[name];

            }

            return null;

        }

    }

}


Now when we want to save a user setting or retrieve a user setting we can simple use our helper class.

Example: I wanted to remember the last page the user was on and automatically navigate the user to that page when they returned. Whenever a user navigated to a page I would simple store the name of the current page

IsolatedStorageManager .SaveIntoIsolatedStorage(pageName, Constants.CURRENT_PAGE);

Now when the user leaves your application and returns, we can check to see what page they were on before and return them to that page.

if (IsolatedStorageManager.Contains(Constants.CURRENT_PAGE)) //user was here before

{

   NavigateToPage((string)IsolatedStorageManager.LoadFromIsolatedStorage(Constants.CURRENT_PAGE));

 }

 else

  NavigateToPage("Home");

}

Posted in: c# | silverlight

Tags: ,

Silverlight confirm dialog imported by MEF

April 6, 2010 at 4:55 PMdsoltesz

I wanted to created a user control that would allow to me ask the user a question and then based on their answer, do something, hence I needed a confirm dialog.  I wanted to be able to use this control by adding a reference or by using MEF just to export/import my confirm dialog.  To start, I created a new silverlight application and then added a childwindow control and named it "ConfirmWindow".  Since I wanted to be able to export this control via MEF, I also created an interface for our confirm dialog.

<controls:ChildWindow x:Class="Axis.iDoc.Window.ConfirmWindow"

         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"

           Title="Confirm">

    <Grid x:Name="LayoutRoot" Width="400" Margin="2">

        <Grid.RowDefinitions>

            <RowDefinition />

            <RowDefinition Height="Auto" />

        </Grid.RowDefinitions>

 

        <TextBlock x:Name="tbMessage" TextWrapping="Wrap" Grid.Row="0" />

        <Button x:Name="CancelButton" Content="No" Click="CancelButton_Click"  Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />

        <Button x:Name="OKButton" Content="Yes" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />

    </Grid>

</controls:ChildWindow>

Code behind

[Export(PartContracts.ConfirmWindow,typeof(IConfirmWindow))]

    public partial class ConfirmWindow : ChildWindow,IConfirmWindow

    {

        public ConfirmWindow()

        {

            InitializeComponent();

            this.Closed += (s, e) => dialogResult(this.DialogResult);

        }

        Action<bool?> dialogResult;

        public void Show(string message,Action<bool?> windowClosedFunc)

        {

            if (windowClosedFunc != null)

            {

                dialogResult = windowClosedFunc;

            }

 

            tbMessage.Text = message;

            this.Show();

        }

 

        private void OKButton_Click(object sender, RoutedEventArgs e)

        {

            this.DialogResult = true;

        }

 

        private void CancelButton_Click(object sender, RoutedEventArgs e)

        {

            this.DialogResult = false;

        }

 

 

    }

 

 

You will notice that I have an Export attribute at the top because I want to be able to export my confirm window via MEF.

 

IConfirmWindow.cs

public interface IConfirmWindow

   {

       void Show(string message, Action<bool?> windowClosedFunc);

   }


 

To use this control you can either add a reference to this silverlight application or you can import it via MEF. I decided to import it via MEF.

 

private Lazy<IConfirmWindow> confirmWindow;

 

       [Import(PartContracts.ConfirmWindow, AllowDefault = true, AllowRecomposition = true)]

       public Lazy<IConfirmWindow> ConfirmWindow

       {

           get { return confirmWindow; }

           set

           {

               if (confirmWindow == value)

               {

                   return;

               }

               confirmWindow = value;

 

           }

       }

 

 I created a little helper method to show confirm window.

 

 

public void ShowConfirmWindow(string message, Action<bool?> windowClosedAction)

 

if (ConfirmWindow != null)

 

 To use the confirm dialog is the same regardless if you added a reference to it or you imported from MEF.

 

private void deleteButton_Click(object sender, RoutedEventArgs e)

{

   _window.ShowConfirmWindow("Are you sure you want to delete item?", d => confirmDelete_Closed(d));

}

void confirmDelete_Closed(bool? dialogResult)

{

    if (dialogResult.HasValue && dialogResult.Value)

    {

       //user wants to delete   

    }

}

 

{

ConfirmWindow.Value.Show(message, windowClosedAction);

}

}

 

{

 

Posted in: .NET | c# | silverlight

Tags: ,