Welcome to WindowsClient.net | Sign in | Join
in

WindowsClient.net

Learnings..

March 2008 - Posts

  • (WPF)Figure out dynamically if the ListView ScrollViewer is showing!!

    I recently faced a situation where i had a databound ListView with a ItemTemplate consisting of a text block.The ListView is of a predefined height and width and the TextBlock is textwrapped and set to the same width as the ListView..

    Everything worked fine till the number of items in the ListView increased resulting in the Default ScrollViewer of the ListView showing up showing Vertical as well as horizontal scroll bars.The annoying aspect is that the scrollviewer uses the real estate of the ListView...

    So now the TextBlock can no longer be seen completely as it is hidden behind the vertical scrollbar and i need to use the horizontal scroll bar to view the complete text...I am sure many have faced this particular issue...

    So one way around is to check if the ScrollBar can be seen and if so then adjust the width of the text block.This is all fine except that there is no direct way to extract the scrollviewer of the ListView....

    The following steps can help you

    1. Hook on to the ListView.LayoutUpdated event
    2. The following lines of code in the LayoutUpdated event handler help extract the ScrollViewer(consider the Listview is called listView)
    Decorator border = VisualTreeHelper.GetChild(listView, 0) as Decorator;//Border is the first child of a Listview

    ScrollViewer scroll = border.Child as ScrollViewer;

         3.  Now we need to figure out of the ScrollBar is visible or not. ScrollViewer.VerticalScrollBarVisibility or ScrollViewer.IsVisible etc all proved useless in this case.

    ScrollViewer.VerticalScrollBarVisibility is Auto in this case and will show the value of Auto whether its seen or not. ScrollViewer.IsVisible will return true as we have not set it to false coz we want it to show up as and when required.

    The only property i could make use of here to figure out if the scrollViewer is showing a vertical scrollbar is

    ScrollViewer.ScrollableHeight. If the value is set to 0 then the scrollbar is not visible and if it is greater than 0 then it is visible.

    So using these steps i could figure out when i need to resize my textblock to prevent it from hiding behind the vertical scroll bar.

    Somehow i am not  very happy  about the use of ScrollViewer.ScrollableHeight but thats all i could find to help me...if you do figure out a better way...do drop me a line:-)

     Till then..

    Anshulee

     

  • Multiple Level Master Detail Binding in WPF(XAML)

    I’ve seen a couple of developers fumble with a LOT of Code when asked to implement a 2-3 level Master –detail form.

    So I put together a bit of code to showcase how easily it can be done with virtually no code (alteast no code behind!!) in WPF

    Consider the following problem statement:

    Create a form which lists a set of families in a dropdown.(Level 1)

    Depending on the family selected list the members of the family. List the sons and daughters in a dropdown(Level 2)

     

    Depending on the son or daughter selected, list their friends in a dropdown(Level 3)

    So your form should look like

    To make things more interesting, all this information about the families comes from this XML Document. Family.xml

    So how do we do this in WPF?.

    The following 4 Step process should suffice!!

    1.       Create an XML Data provider for the XML  Document and set the XPath to the Family Node

    <XmlDataProvider x:Key="dataSource" Source="Family.xml" XPath="/Families/Family"></XmlDataProvider> 

    2.       Create the UI in 2 layers  i.e there should be 3 grids let’s call them the  FamilyGrid, Son Grid and Daughter Grid

    So the structure is

    <Grid x:Name=”FamilyGrid”>

    <..Place the Level 1 controls here…i.e Family combobox, Father and Mother text blocks-->

                    <Grid  x:Name=”SonGrid”>

    <.. Place the Level 2 and Level 3 controls here..i.e the “Son” Combo box followed by the Son’s friends..>

                    </Grid>

    <Grid  x:Name=”DaughterGrid”>

    <.. Place the Level 2 and Level 3 controls here..i.e the “Daughter” Combo box followed by the Daughter’s friends..>

    </Grid>

                    </Grid>

    3.       Set the DataContexts of the Grids

    a.       Family Grid: Set the DataContext to the Family Node

    <Grid x: Name=”FamilyGrid” DataContext="{Binding Source={StaticResource  dataSource}}">

    b.      Son Grid: Set the DataContext to the “Son” Node within the current Binding

    <Grid x:Name="SonGrid" DataContext="{Binding XPath=Children/Sons/Son}">

    c.       Daughter’s Grid: Set the DataContext to the “Daughter” Node within the current Binding

    <Grid x:Name="DaughterGrid" DataContext="{Binding XPath=Children/Daughters/Daughter}">

    4.       Bind the Comboboxes to the required fields and set the IsSynchronizedWithCurrentItem= true

     As Highlighted above the key points here are

    ·         The DataContexts of the Grids which are set to the level of information which we want to show. Whenever a control does an “ItemSource= {Binding…}, the compiler will travel up the UI Heirarchy to find the first not- null data context.So it helps to set the datacontext at the “container” level if mutiple controls need to refer to a common data source.

     

     Since we have a hierarchy of grids and the family grid refers to the /Families/Family Node, we just need to keep setting the DataContext={Binding , XPath= <the XPath to the Node following the family node>}. DataContext={ Binding…} will take you to the /Families/Family node and the XPath will take you to your desired node

     

    ·         The Property IsSynchronizedWithCurrentItem which is being set to true in the comboboxes is the key here.When you bind a set of data to a value select control and set IsSynchronizedWithCurrentItem = true, what you are saying is “From this point onwards consider this data item as the selected item and refer to it for data for the ensuing controls”

     

    So when you select a family in the family combobox, and make it the “Current Selected” data item, the other comboboxes will refer to the data present in the selected family at the specified path , so Family/Son will search for the Son node within the selected Family

     So using a combination of DataContexts to refer to different levels of data and IsSynchronizedWithCurrentItem to set the currently selected data you can go upto n levels of master details binding,and you wudn’t have written a single line of code in you .cs fileJ

     

     You can find the solution for the above example hereMasterDetailBinding.zip.

     

    Happy Detailing!

    Anshulee

     

  • The One Stop Shop for Mix 08 related downloads

    I was going berserk trying to keep a tab of WHAT ALL has been advertised on Mix, before i hit this site

    Thanks to Sarah Perez for collating everything and sharing with us!!

    So Sarah's blog along with http://sessions.visitmix.com/ should keep you busy over the weekend!!

     

    Posted Mar 07 2008, 12:54 PM by Anshulee with no comments
    Filed under:
  • Mix 2008 Sessions- Already available

    There is still hope for us "unfortunate" ones who cannot attend the Mix 08 sessions live!!

    Get updated with the latest presentations uploaded at

    http://sessions.visitmix.com/

    I love the presentation of this site! 

    Happy Viewing!!

    Anshulee

    Posted Mar 07 2008, 12:38 PM by Anshulee with no comments
    Filed under:
  • Structured Navigation Using Page Functions!

    One of the new features WPF has given us windows programmers is the "Page" as the supposed equivalent of the html web page..information can now flow from one page to another as in a website by linking one page to another via a hyperlink .This gives users the  familiar web experience(and looks much better than windows popping up with every click!!)..

    Along with pages, WPF also introduces a concept known as Page Functions..but before i go there, lets examine WHY we need them!

    Hyperlink driven navigation in pages has the following drawbacks

    a) It is difficult to pass information between the host page and the calling page

    b) In case the host page called a task page to do some work , its difficult for the host page to know if the work was actually completed or not

    c) In some cases it is desired that the user should NOT be able to navigate back to the task page. For example once he has submitted the information he shouldn’t be allowed to go back using the Navigation service and change it. This is very difficult to achieve

    The first 2 points above i.e. a and b can be achieved in the traditional page + hyperlink combination using Application scope properties to pass information between them, though not in a very structured manner. However it is very difficult to remove the task page reference from the history.

     

    WPF has solved these issues by creating Page Functions.

    Essentially, page functions enable a style of navigation that is analogous to functions in procedural languages, which typically involves the following:

      • Calling a function.
      • Passing parameters to the function.
      • Performing processing from the function.
      • Calling other functions from the function.
      • Return results from the function to the calling code.
      • Cleaning up.

    Given below is the definition of a Page Function. To create a Page function you simple do a AddNewItemàPage Function into your solution.

     

    PageFunction.xaml

    <PageFunction

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

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

        xmlns:sys="clr-namespace:System;assembly=mscorlib"

        x:Class="CSharp.TaskPageFunction"

        x:TypeArguments="sys:String"

        Title="Task Page Function" WindowWidth="250" WindowHeight="150">

      <Grid Margin="10"></Grid>

    </PageFunction>

     

    PageFunction.xaml.cs

    public partial class TaskPageFunction : PageFunction<String>

    {

        public TaskPageFunction()

        {

            InitializeComponent();

        }

    }

    The declaration is pretty much similar to a page. However Page Function is a generic class and needs a declaration of the Type of the value it will return.This is set in the  x:TypeArguments="sys:String" in the xaml configuration and correspondingly as <String> in the Page.xaml.cs file

    You can create your own custom types and use your page function to return custom information (If you are interested leave me a comment and i can upload an example!).

     

    Now that we know the concept of Page Function and how to define it. We’ll see how to create, call, pass values and get the results from a page function

     

    Creation and calling and passing value: It is same as creating an instance of a Page and navigation to it

    Say

    TaskPageFunction taskPageFunction = new TaskPageFunction()//Call an overloaded constructor if you want to pass information to it,

     this.NavigationService.Navigate(taskPageFunction); Getting return value from the task page

    In order to pass values back to the Calling page, Task page calls a method called OnReturn(). OnReturn is a protected virtual method which will be called with an instance of Generic ReturnEventArgs of the type same as the Type arguments you had specified for the page function.

     

    So whatever data you want to return will be sent to the OnReturn() function.

    For example in the Page function definition we created above, on clicking a submit button you want to pass the text entered by the user into a textbox called “NameTextBox” the code will be as under

     Public void SubmitClicked(sender object, RoutedEventAgrs args){OnReturn(new ReturnEventArgs<string>(this. NameTextBox.Text));} 

    The OnReturn() method in turn fires the Return event of the task page which the calling class has to hook onto.

     

    To summarize the following 3 parts of the code are needed to complete the navigation

     

    //create the page function, hook onto its Return event and navigate to it

    TaskPageFunction taskPageFunction = new TaskPageFunction()taskPageFunction.Return += taskPageFunction_Return; this.NavigationService.Navigate(taskPageFunction); 

    // the Page function will call ONReturn on completing its task

    OnReturn(new ReturnEventArgs<string>(this. NameTextBox.Text));

    The Calling page method delegated to receive the event will get called and will extract the information from the event args passed to it

     void taskPageFunction_Return(object sender, ReturnEventArgs<string> e) {  MessageBox.Show(“Name  Is “+ e.Result}      Removal of Page function ref from the Navigation history

    Every PageFunction /Page has a property called as RemoveFromJournal .Setting it to true removes it from the navigation history after the page has been navigated away from.

          By default a Page function has RemoveFromJournal set to true. So it will be removed  from history once its OnReturn has been called.

     

    Oh btw...this form of Navigation is called Structured Navigation in WPF Terminology!!

     

    Enjoy!

    Anshulee

  • Know me!!

    Oops..i didn't really introduce myself did i?? Well..here

    Name:- Anshulee Asthana

    Experience:- 4.5 years

    Hobbies:- Playing!!..may be no good at all..but i still enjoying playing...anything ...but it better be outdoors!!

    Tech Interests:- Anything to do with Windows Programming!!

    What am i doing here??:- Well i am here to show off a little and to learn a lot from you!!

  • Silverlight blueprint for Sharepoint!!

    Looks like Microsoft really does believe in creating an integration between all of its technologies and frameworks.

    The latest announcement at the Sharepoint conference at Seattle speaks of a Silverlight Blueprint for SharePoint .. This will allow SharePoint Developers building web parts to take advantage of Silverlight user interface components.

    Check it out!

    http://msdn2.microsoft.com/en-us/sharepoint/cc303301.aspx

    --Anshulee 

     

Page view counter