Selasa, 24 Juni 2014

WindowsPhone 8.0 vs WindowsPhone 8.1:New ways for detecting Page Orientations on Phone(C#-XAML)

Introduction:

It is very important that your app looks good and functions perfectly in all orientations .And it is the best way to attract app users,fortunately windows phone can provide best strategies for making our app in all orientations ,but in some times we may need to  detect page orientations(portrait up, portrait down, landscape left, landscape right) and dynamically change the our UI design.However previously in windowsphone 8.0 we are detecting page orientations with help of 'OrientationChanged' event,but  in windowsphone store 8.1 this event is directly no longer available,so this post is explained about 'What are the alternative ways for detecting page orientation in wp8.1".In addition this post is explained about "SimpleOrientation" sensor class and how it is useful for detecting page orientations in windows phone store 8.1.

Building the sample:

  • Make sure you’ve downloaded and installed the Windows Phone SDK. For more information, see Get the SDK.
  • I assumes that you’re going to test your app on the Windows Phone emulator. If you want to test your app on a phone, you have to take some additional steps. For more info, see Register your Windows Phone device for development.
  • This post assumes you’re using Microsoft Visual Studio Express 2013 for Windows.
  • This sample is having two projects for both WindowsPhone 8.0 and WindowsPhone 8.1

Description:

Ok,lets start to knowing about page orientations in both windowsphone 8.0 and windowsphone 8.1 .And what's the differences while detecting page orientations 

WindowsPhone 8.0:


In wp8.0 it is very simple,we can detect page orientations with help of OrientationChanged event like



XAML

<phone:PhoneApplicationPage  
    x:Class="OrientationWp8._0.MainPage"  
.............  
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" 
OrientationChanged="PhoneApplicationPage_OrientationChanged">
Here 'SupportedOrientation' defines the orientations that could be supported by your page,'Orientation' defines the current orientation of the page both are available from Microsoft.Phone.Controls namespace  

In c# at corresponding event ,we can get dynamic page orientation changes like this 
C#

private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e) 
        { 
            PageOrientation orientation = e.Orientation; 

            StatusTxtBlck.Text = "Curren Page Orientation is: " + orientation.ToString(); 
            if (orientation == PageOrientation.LandscapeRight) 
            { 
                txtOrientation.Text = orientation.ToString();//LandscapeRight 
            } 
            else if ((orientation & PageOrientation.LandscapeLeft) == PageOrientation.LandscapeLeft) 
            { 
                txtOrientation.Text = orientation.ToString();//LandscapeLeft 
            } 
             
            else if ((orientation & PageOrientation.Portrait) == PageOrientation.Portrait) 
            { 
                txtOrientation.Text = orientation.ToString();//PotraitUp 
            } 
             
            /******** to check for landscape******/ 
            if ((orientation & PageOrientation.Landscape) == PageOrientation.Landscape) 
            { 
                txtOrientation.Text = orientation.ToString();//Landscape 
            } 
           
        }
If you want to set page to specific orientation ,you can do like this.

C#

private void OrientationBtn_Click(object sender, RoutedEventArgs e) 
        {   
            //to support only landscape 
            SupportedOrientations = SupportedPageOrientation.Landscape; 
 
            //to support only potrait 
            SupportedOrientations = SupportedPageOrientation.Portrait; 
 
            //to support both landscape & potrait 
            SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape; 
        }
for example i taken the following design

XAML

<Grid x:Name="LayoutRoot" 
        <Grid.RowDefinitions
            <RowDefinition Height="Auto"/> 
            <RowDefinition Height="*"/> 
        </Grid.RowDefinitions> 
        <Grid
            <StackPanel
                <TextBlock FontSize="25" Text="WindowsPhone 8.0 Orientations" Name="TileTxt" VerticalAlignment="Top" Margin="10" TextWrapping="Wrap" Foreground="Yellow"/> 
                <TextBox  Name="txtOrientation" VerticalAlignment="Top"  TextWrapping="Wrap" Foreground="#FF1CB8D1"/> 
                <Button Content="Tap here to set your orientation" Name="OrientationBtn" Click="OrientationBtn_Click"/> 
                <TextBlock Name="StatusTxtBlck" Margin="10" /> 
            </StackPanel> 
        </Grid> 
    </Grid> 
and see how above above Ui design effected, when change the page orientations from your emulator toolbar/device rotation 



WindowsPhone 8.1:

So as we have earlier discussion from 'Introduction' section,now 'OrientationChanged' event is no longer available for windowsphone store 8.1 .
However even we miss it,there is two ways for detecting page orientations
  • SizeChanged Event
  • SimpleOrientation sensor class
1)SizeChanged event:

SizeChanged event is useful for detecting the page orientation changes when it occurs.

XAML

<Page 
    x:Class="OrientationWp.MainPage" 
..... 
SizeChanged="Current_SizeChanged">
and in c# at corresponding event ,we can get dynamic page orientation changes like this 

C#

private void Current_SizeChanged(object sender, SizeChangedEventArgs e) 
        { 
            string CurrentViewState = ApplicationView.GetForCurrentView().Orientation.ToString(); 
            StatusTxtBlck.Text = "Curren Page Orientation is: " + CurrentViewState; 
            if (CurrentViewState == "Portrait"
            { 
               //To Do UI for potrait 
            } 
 
            if (CurrentViewState == "Landscape"
            { 
                //To Do UI for landscape   
            } 
        }
2)SimpleOrientation Sensor:

As like previous event 'SizeChanged', SimpleOrientation sensor is also to determine the current device orientation (portrait up, portrait down, landscape left, landscape right) as well as the device's face-up or face-down status.And this class sensor readings which is equlal to page orientations like

Portrait Up         ->  NotRotated
Landscape Left   ->  Rotated90DegreesCounterclockwise
Portrait Down     ->  Rotated180DegreesCounterclockwise
Landscape Right ->  Rotated270DegreesCounterclockwise

Note: To work with SimpleOrientation sensor,The device or emulator that you're using must support an accelerometer.

Ok,lets start work with this sensor class 

Step1:

Get default page orientation,After creating an object for sensor,and finally assign the handle for sensor orientation changed event like this,

C#

private SimpleOrientationSensor _simpleorientation; 
        public MainPage() 
        { 
            this.InitializeComponent(); 
             
            _simpleorientation = SimpleOrientationSensor.GetDefault(); 
            // Assign an event handler for the sensor orientation-changed event 
            if (_simpleorientation != null
            { 
                _simpleorientation.OrientationChanged += new TypedEventHandler<SimpleOrientationSensor, SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged); 
            } 
        }
Here you should check sensor object whether it is null or not.if it is null means your device doesn't support the above sensor. 

Step2:

In corresponding event ,access page orientation changes like this way,

C#

private async void OrientationChanged(object sender, SimpleOrientationSensorOrientationChangedEventArgs e) 
        { 
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 
            { 
                SimpleOrientation orientation = e.Orientation; 
                switch (orientation) 
                { 
                    case SimpleOrientation.NotRotated: 
                        //Portrait Up 
                        txtOrientation.Text = "Not Rotated"
                        break
                    case SimpleOrientation.Rotated90DegreesCounterclockwise: 
                        //LandscapeLeft 
                        txtOrientation.Text = "Rotated 90 Degrees Counterclockwise"
                        break
                    case SimpleOrientation.Rotated180DegreesCounterclockwise: 
                        //PortraitDown 
                        txtOrientation.Text = "Rotated 180 Degrees Counterclockwise"
                        break
                    case SimpleOrientation.Rotated270DegreesCounterclockwise: 
                        //LandscapeRight 
                        txtOrientation.Text = "Rotated 270 Degrees Counterclockwise"
                        break
                    case SimpleOrientation.Faceup: 
                        txtOrientation.Text = "Faceup"
                        break
                    case SimpleOrientation.Facedown: 
                        txtOrientation.Text = "Facedown"
                        break
                    default
                        txtOrientation.Text = "Unknown orientation"
                        break
                } 
            }); 
        }
If you want to set page to specific orientation ,you can do like this.

Note: Above 'OrientationChanged' changed event will not be fire,when we set orientaion through code.And it will be fire only when user switch the orientation from emulator toolbar/device rotations. 

C#

private void OrientationBtn_Click(object sender, RoutedEventArgs e) 
        { 
            /***To support both***/ 
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.None; 
             
            /***To support only landscape***/ 
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape; 
 
            /***To support only potrait 90 degress clock wise***/ 
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.Portrait; 
             
            /***To flip 180 degrees from potrait mode***/ 
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.PortraitFlipped; 
 
            /***To flip 180 degrees from landscape mode***/ 
            DisplayInformation.AutoRotationPreferences = DisplayOrientations.LandscapeFlipped; 
        }
Note: If your app really can't work in multiple orientations, you might want to lock it to a specific format by setting the preferred orientations in the Package.appxmanifest file. Clearly this is not ideal, but if the design is
fixed, it might be your only choice.

Editing the Package.appxmanifest file in Visual Studio








However for the final step i taken the following design

XAML

<Grid
        <StackPanel
        <TextBox Header="WindowsPhone Store Orientations" Margin="10"  Name="txtOrientation" VerticalAlignment="Top" TextWrapping="Wrap" Foreground="#FF1CB8D1"
            <TextBox.HeaderTemplate
                <DataTemplate
                    <TextBlock Text="{Binding}" FontSize="25" Foreground="Yellow"/> 
                </DataTemplate> 
            </TextBox.HeaderTemplate> 
        </TextBox> 
            <Button Name="OrientationBtn"  Content="Tap here to set your orientation" HorizontalAlignment="Center" Click="OrientationBtn_Click"/> 
            <TextBlock Name="StatusTxtBlck" Margin="10" FontSize="20"/> 
        </StackPanel> 
    </Grid>
Here observe TextBox control having header property which is not available in windows phone 8.0.So please read about latest TextBox control from here.And see how above above Ui design effected, when change the page orientations from your emulator toolbar/device rotation 



Source file at: OrientationSampleWP

    Note: Please share your thoughts,what you think about this post,Is this post really helpful for you?otherwise it would be very happy ,if you have any thoughts for to implement this requirement in any another way?I always welcome if you drop comments on this post and it would be impressive.

    Follow me always at  

    Have a nice day by  :)


    Kamis, 19 Juni 2014

    WindowsPhone ListBox Search: HightLight the search result text with specific color(C#-XAML)

    Introduction:

    In prev post i was explained about get child items in windowsphone,this post is explained about "How to filter/search the listbox items based on text entered in SearchTextBox?" & "How to highlight the search text color in every mapped listbox items?".Oh apart from these two questions ,for the first question there is lot of resources are available to do that,in other hand second question is very interesting requirement and it is little bit complicated to dynamically highlight listbox items text color  which is mapped by text entered in SearchTextBox . Because indirectly it is the way of communication between SearchTextBox & ListBox DataTemplate controls,so we need to get child items of listbox datatemplate and then dynamically format the child items text color with " Run " object element.However this post will gives you simple solution for above both two questions.

    Building the sample:

    This sample is targeted on windowsphone 7.1 OS.

    Description:

    I hope you understand the sample in earlier discussion from "Introduction" section.if you still any confusions see the below image to understand the sample 
    Now its time to start implement above functionality in windowsphone using c# & xaml.So we need to have following steps:

    1)ListBox binding with C#-XAML in windowsphone:

    XAML

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"
                <Grid.RowDefinitions
                    <RowDefinition Height="80"/> 
                    <RowDefinition Height="auto"/> 
                </Grid.RowDefinitions> 
                <TextBox Grid.Row="0"  x:Name="SearchTextBox" TextChanged="contactFilterString_TextChanged" Margin="0,0,2,10"/> 
                <ListBox BorderBrush="#FF141EE4" Height="auto" BorderThickness="2" MaxHeight="580" Grid.Row="1" x:Name="listBoxobj" LayoutUpdated="listBoxobj_LayoutUpdated"
                    <ListBox.ItemTemplate
                        <DataTemplate
                            <Grid Background="Gray" Width="480"
                                <Border BorderBrush="White" BorderThickness="1"
                                    <Grid
                                        <Grid.RowDefinitions
                                            <RowDefinition Height="Auto"/> 
                                            <RowDefinition Height="Auto"/> 
                                         </Grid.RowDefinitions> 
                                        <TextBlock Grid.Row="0" x:Name="NameTxt" TextWrapping="Wrap" Text="{Binding Name}" FontSize="28" Foreground="White"/> 
                                        <TextBlock Grid.Row="1" x:Name="AddrTxt"  TextWrapping="Wrap" Text="{Binding Address}" /> 
                                    </Grid> 
                                </Border> 
                            </Grid> 
                        </DataTemplate> 
                    </ListBox.ItemTemplate> 
                </ListBox> 
            </Grid>

    Here Parent Grid(i.e ContentPanel) having two Rows ,in first row i placed the TextBox(i.e SearchTextBox)for entering search text.And  other hand in second row i placed ListBox control ,in  listbox DataTemplate i was taken Border inside Grid to make it as listboxitem having white border brush.And in Border there is two TextBlocks(NameTxt,AddrTxt) for binding Name & Address properties of 'Profile.cs' class

    In c# we need to create class called 'Profile.cs' with properties 'Name &Address'.And make sure this properties should be match with binding objects names which we are earlier done in listbox datatemplate of above Xaml code .
    C#

    public class Profile : INotifyPropertyChanged 
        { 
            public string _name; 
            public string _addr; 
            public string Name 
            { 
                get { return _name; } 
                set { _name = value; NotifyPropertyChanged("Name"); } 
            } 
     
            public string Address 
            { 
                get { return _addr; } 
                set { _addr = value; NotifyPropertyChanged("Address"); } 
            } 
     
            public event PropertyChangedEventHandler PropertyChanged; 
            private void NotifyPropertyChanged(string property) 
            { 
                if (PropertyChanged != null
                { 
                    PropertyChanged(thisnew PropertyChangedEventArgs(property)); 
                } 
            } 
        }
    Take one ObservableCollection global object(i.e UserProfileList) for our 'Profile' class .And add some static items to list,finally bind that list to our ListBox(i.e listBoxobj).

    C#

    /**Creating ObservableCollections object to Profile.cs**/ 
    ObservableCollection<Profile> UserProfileList = new ObservableCollection<Profile>(); 
    /**Add some static items to above UserProfileList**/ 
     private void Listloading() 
            { 
                UserProfileList.Add(new Profile { Name = "Subbu", Address = "Hyderbad, India[441]" }); 
                UserProfileList.Add(new Profile { Name = "Raju", Address = "Hyd,India[91] " }); 
                UserProfileList.Add(new Profile { Name = "Sudhar", Address = " UK[44]" }); 
                UserProfileList.Add(new Profile { Name = "Sudhar Sharma", Address = "Bangalore" }); 
                UserProfileList.Add(new Profile { Name = "Navadeep", Address = "Mumbai" }); 
                UserProfileList.Add(new Profile { Name = "Anuroop", Address = "Pune" }); 
                UserProfileList.Add(new Profile { Name = "Kalyan", Address = "New Delhi" }); 
                UserProfileList.Add(new Profile { Name = "Venky", Address = "Kadapa" }); 
                UserProfileList.Add(new Profile { Name = "Sai", Address = "Canada" }); 
    /**Finally bind list to our ListBox**/ 
    listBoxobj.ItemsSource = UserProfileList; 
     
    Wow now we are done first step with very interestingly,so now lets go for second step.


    2)How to implement listbox search functionality in windowsphone c#-xaml:


    Now its time to filter listbox items based on text entered in SearchTextBox,so when text entering on the SearchTextBox we need to filter listbox items,thats why i taken 'TextChanged' event  of SearchTextBox.Because TextChanged event is fired when entered text is changed ,so this event is best fit for filtering listbox items.

    C#

     bool LayoutUpdateFlag = true;//this is for handling layout upadated event 
    private void contactFilterString_TextChanged(object sender, TextChangedEventArgs e) 
            { 
               //filter items with help of lambda expression 
                this.listBoxobj.ItemsSource = UserProfileList.Where(w => w.Name.ToUpper().Contains(SearchTextBox.Text.ToUpper()) || w.Address.ToUpper().Contains(SearchTextBox.Text.ToUpper())); 
                LayoutUpdateFlag = true
                
            } 
    Note: Here i am using the bool variable 'layourUpdateFlag' ,which is useful for handling listbox 'LayoutUpdated' event in further step 3.Now we are done search functionality.Lets go for most interesting step .


    3)Highlight the search result from Listbox items c#:

    This step is most interesting and as well as little bit complicated.but after completing this step,we would feel like 'how it is very easy?".Ok lets see :)
    So first we need helper class(i.e SearchVisualTree) for finding child items from listboxitem ,and then dynamically  format the child items  with 'Orange' color(i.e using Run element)  based on search text using separate method(i.e HighlightText())

    C#

    /** This helper class is for finding listbox datatemplate control elements**/ 
    private void SearchVisualTree(DependencyObject targetElement) 
            { 
     
                var count = VisualTreeHelper.GetChildrenCount(targetElement);//get count targeted dependecnyobject 
     
                for (int i = 0; i < count; i++) 
                { 
                    var child = VisualTreeHelper.GetChild(targetElement, i);//detecting listboxitem child items 
                    if (child is TextBlock) 
                    { 
                        textBlock1 = (TextBlock)child; 
                        prevText = textBlock1.Text; 
                        if ((textBlock1.Name == "NameTxt" || textBlock1.Name == "AddrTxt") && textBlock1.Text.ToUpper().Contains(SearchTextBox.Text.ToUpper())) 
                        { 
                            HighlightText();//after finding textblock child item call method for highligh color 
                        } 
                    } 
                    else 
                    { 
                        SearchVisualTree(child);//repeat method call until targeted dependency found child items 
                    } 
                } 
            } 
     
    /**This method is for highlight the search text**/ 
      private void HighlightText() 
            { 
                if (textBlock1 != null
                { 
                    string text = textBlock1.Text.ToUpper(); 
                    textBlock1.Text = text; 
                    textBlock1.Inlines.Clear(); 
     
                    int index = text.IndexOf(SearchTextBox.Text.ToUpper());//getting index of search text from listboxitem textblock 
                    int lenth = SearchTextBox.Text.Length; 
     
                    if (!(index < 0)) 
                    { 
     
                        Run run = new Run() { Text = prevText.Substring(index, lenth) }; 
                        run.Foreground = new SolidColorBrush(Colors.Orange);//format search text color with orange 
                        textBlock1.Inlines.Add(new Run() { Text = prevText.Substring(0, index) }); 
                        textBlock1.Inlines.Add(run); 
                        textBlock1.Inlines.Add(new Run() { Text = prevText.Substring(index + lenth) }); 
                    } 
                } 
            }
    Finally we need to handle above method calls,so when listbox is updated by search text  then set 'LayoutUpdateFlag = true' and we need to highlight searchitems,so i taken the listbox 'LayoutUpdated' event and call the above helper class


    C#

    private void listBoxobj_LayoutUpdated(object sender, EventArgs e) 
            { 
                if (LayoutUpdateFlag) 
                { 
                    SearchVisualTree(listBoxobj); 
                } 
                LayoutUpdateFlag = false
            }
    So sweet,now we are done all above three steps :listbox databinding,listbox search & finally hilghlight the search result with sepecific color.

    Source file at: ListboxSearchSample

      Note: Please share your thoughts,what you think about this post,Is this post really helpful for you?otherwise it would be very happy ,if you have any thoughts for to implement this requirement in any another way?I always welcome if you drop comments on this post and it would be impressive.

      Follow me always at  
      Have a nice day by  :)