Thursday, May 8, 2008

Using Background Process in WPF

WPF applications often needs to call time consuming methods or processes, the time consuming methods or processes can be, huge time consuming calculation or perhaps a web service call. In case of WPF specially XBAP (wpf browser application) which run on remote client machines browser, this sort of calls can make your user interface unresponsive.  I am working with WPF for more than four month. Lot of things come in to way and dealt with nicely. Well in this post I am going to share a simple trick for avoiding unresponsiveness of user interface. We have already used this technique in many cases in our application, but this is for WPF.

The "Thread & Invoke"

BackgroundWorker is a very smooth and useful tool for our purpose of making more responsive UI(user interface). Before discussing more about BackgroundWorker lets take a flash back of legacy technique (which is pretty smart)  implementation of making  more responsive UI. Previously I used threading for implementing such kind of UI smoothness. What I did is to create a background thread and call expansive operation on that thread. When the job is finished use the "MethodInvoker" method to let know the UI thread that the job is finished. And this model is called asynchronous model. And this is quite smart model and rest of the models are based on this approach. Here is a quick code snippet for demonstration the technique.

//first start the method with tread
System.Threading.ThreadStart ts = new System.Threading.ThreadStart(ExpansiveMethod);
System.Threading.Thread t = new System.Threading.Thread(ts);
t.Start();
protected void ExpansiveMethod()
{
//Very expansive call will go here...
//after the job is finished call method to update ui
MethodInvoker updaterMI = new MethodInvoker(UpdateChange);
this.BeginInvoke(UpdateChange);
}
protected void UpdateChange()
{
//again back to main ui thread
}


 


The "Background Worker"


Okay, its time to use the BackgroundWorker. An amazing thing about background worker is, its simple to use.  First, lets see what a background worker is. "BackgroundWorker" is a class under "System.ComponentModel" which executes an operation on a separate thread. Which is introduced from dot net framework 2.0. Things are again pretty simple just like tread, All you have to do is instantiate a BackgroundWorker and subscribe its events, and call the "RunWorkerAsync()" method. Lets put a code snippet. Since we are programmers we understand code better.




void MyMethodToCallExpansiveOperation()
{
//Call method to show wait screen
BackgroundWorker workertranaction = new BackgroundWorker();
workertranaction.DoWork += new DoWorkEventHandler(workertranaction_DoWork);
workertranaction.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workertranaction_RunWorkerCompleted);
workertranaction.RunWorkerAsync();
}
void workertranaction_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Call method to hide wait screen
}
void workertranaction_DoWork(object sender, DoWorkEventArgs e)
{
//My Expansive call will go here...
}



As you can see in above code I have subscribed two event "DoWork" (which is the main function) and "RunWorkerCompleted", In dowork event handler we will put our expansive time consuming operations, as the name imply's RunWorkerCompleted event is fired when the work is finished . BackgroundWorker also has "ProgressChanged" event which is used to let the main UI thread know how much work is completed.


The "Dispatcher"


In few cases the BackgroundWorker needs to access the main UI thread. In WPF we can use "Dispatcher" which is a class of "System.Windows.Threading" and a delegate to access the main thread. First of all we have to declare a delegate for our candidate methods, and then use the delegate to call the method using Dispatcher. Dispatcher has few thread priority and you can use various priority from DispatcherPriority enum. "Send" has the highest priority in DispatcherPriority.




//delegate for our method of type void
public delegate void Process();
//and then use the dispatcher to call the method.
Process del = new Process(UpdateMyUI);
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, del);
void UpdateMyUI()
{
//get back to main UI thread
}



For more reading about this Asynchronous Programming please visit the references.


Reference



Thursday, April 10, 2008

Wpf Image ,Working with Image Source

Hi after a long time I am back in my blog. In this post I will discuss few things about WPF image object. Recently I have been working in a project whose UI Layer is build entirely with windows presentation foundation.

Background

WPF has another way to display image. That is, using BitmapImage object. You can declare BitmapImage tag and in WPF XAML just like Image tag. But in case of BitmapImage the source property is a Uri name is UriSource. Luckily BitmapImage is the source property of Image. Here is a simple code segment of Image and BitmapImage.

ImageSource & BitmapImage

WPF has another way to display image. That is, using BitmapImage object. You can declare BitmapImage tag and in wpf xaml just like Image tag. But in case of BitmapImage the source property is a Uri name is UriSource. Luckily BitmapImage is the source property of Image. Here is a simple code segment of Image and BitmapImage

<Image Width="200" Margin="5" Grid.Column="1" Grid.Row="1" >
<Image.Source>
<BitmapImage UriSource="sampleImages/bananas.jpg" />
</Image.Source>
</Image>

Mouse hover effect

Bellow I have listed few lines of code when i change the image in mouse enter and mouse out of an image object. Of course I am using Uri to define the location of my image then using the Uri to make a new BitmapImage and finally use BitmapImage to assign Image.Source Property.


1: private void btnGoToHome_MouseEnter(object sender, MouseEventArgs e)


2: {


3: this.Cursor = Cursors.Hand;


4: Uri src = new Uri(@"C:/Images/DifferentTransaction_Icon_Active.png");


5: BitmapImage img = new BitmapImage(src);


6: btnGoToHome.Source = img;


7: }


8:


9: private void btnGoToHome_MouseLeave(object sender, MouseEventArgs e)


10: {


11: this.Cursor = Cursors.Arrow;


12: Uri src = new Uri(@"C:/Images/DifferentTransaction_Icon_Normal.png");


13: BitmapImage img = new BitmapImage(src);


14: btnGoToHome.Source = img;


15: }




That's it you are done




Reference




http://msdn.microsoft.com/en-us/library/system.windows.controls.image.aspx

Thursday, March 6, 2008

No Scroll content of wpf xbap in iframe

In my previous blog post i have discussed about how to hide the navigation ui of xbap while you hosting Xbap ( Xaml browser application) in iframe. Note that xbap can be accessed directly from browsers url address and can also be viewed in a iframe in existing web site. In both case user can have contents that requires scrolling.If user developed the xbap application in such a way that the application will be accessed directly form url address, user can archive the goal by adding a "scrollableview" element in your xmal page. bellow a code sample is provided.

   1:  <Page x:Class="CookieTest.Page1"

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

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

   4:        Title="Page1">

   5:      <ScrollViewer>

   6:          <Grid>

   7:              <!--your content will go here–>-->

   8:          </Grid>

   9:      </ScrollViewer>

  10:  </Page>


Next case is if user hosted the xbap application in a iframe. In this case there is a good chance that user will be viewing two vertical scrollbar in user's browser if users existing site's page is long enough to cause view a vertical scroll bar, that is the browser's vertical scrollbar. Xbap host have a defined size, which generally as long and wide as the browser window. So if your content is longer than the size of xbap host, you can loose your content from viewable content area. or you will end up having two scrollbar.Well there is several solutions to this problem. Lets discuss with a simpler version. Make the iframe's height property as long as the xbap that is hosting the xbap. And make sure that your xbap will not grow larger than that. but if your xbap has variable content and has variable height and you got to keep the constant look you need to do some engineering to keep things smooth.Xbap do support get and set of cookie in the site of origin. so do calculate your height for your content in xbap and then set the height as a cookie, make sure you do set the height of the content as a cookie each time the content of xbap has changed, of course in case of the content that cause the xbap to change its size. here is a code example to set cookie for site from xbap.


Application.SetCookie(BrowserInteropHelper.Source, "HEIGHT=" + DemoHeight );


Now in the page, where you hosted your xbap in iframe read the cookie with javascript and the change the height of the iframe. that's it you will have a smooth operation of auto grow or shrink of your xbap and wont cause any extra scrollbar. for reading the cookie do a little engineering for example always track the height cookie with javascript timer based function.




   1:  <script language="javascript" type="text/javascript">

   2:  function getCookie(c_name)

   3:  {

   4:      if (document.cookie.length>0)

   5:      {

   6:        c_start=document.cookie.indexOf(c_name + "=");

   7:        if (c_start!=-1)

   8:          {

   9:          c_start=c_start + c_name.length+1;

  10:          c_end=document.cookie.indexOf(";",c_start);

  11:          if (c_end==-1) c_end=document.cookie.length;

  12:          return unescape(document.cookie.substring(c_start,c_end));

  13:          }

  14:      }

  15:      return "";

  16:  }

  17:  function InCreaseHeight()

  18:  {

  19:      var hight = getCookie('HEIGHT');

  20:      if(hight != "")

  21:      {

  22:          if(document.getElementById('framename')!=null)

  23:          {

  24:              if(hight<600)

  25:              {

  26:                  hight = 600;

  27:              }

  28:              document.getElementById('framename').height = hight;

  29:          }

  30:      }

  31:      setTimeout("InCreaseHeight()",250);

  32:  }

  33:  </script>


one more thing do call the javascript increase height function on body on load event of the page to kick start the process.




   1:  <body onload="InCreaseHeight();">


Reference:


http://www.w3schools.com/js/js_cookies.asp
http://msdn2.microsoft.com/en-us/library/ms750478.aspx#Cookies



Thursday, February 7, 2008

Hide Navigation UI (back, forward button) of Xbap application

Xbap application can be used directly in browser or can be used in a iframe in a web page. when you use directly in browser, browsers nagivation ui is used as xbap navigation UI . But if you use xbap in a iframe xbap host automatically add two back forward button and add a navigation header to your xbap application. if you are using the xbap in a existing web page and in a iframe this cause a little bit problem.

but we can hide the navigation ui very easyly... all we have to do is to set the wpf page object's ShowsNavigationUI property to false... thats all... you are done. But if you are using an "user control" as startup object there is no way to set the property. This works only in case of WPF Page project item template.

But you can still hide the navigation UI... on application's contractor subscribe the navigated event ..

public App()
{
this.Navigated += new NavigatedEventHandler(App_Navigated);
}

void App_Navigated(object sender, NavigationEventArgs e)
{
NavigationWindow ws = (e.Navigator as NavigationWindow);
ws.ShowsNavigationUI = false;
}

Monday, January 28, 2008

Creating web application and web site that run in IIS 7 of windows vista from vs2008

While creating a web site in vs2005 or vs2008 , web site location has three options and the options are 1. File System 2. HTTP 3. FTP

image

Previous version of Visual studio (VS2002,VS2003) supports web application that run only on IIS. User can easily create web applications cause Visual Studio automatically guide the user to create a web application. Since vs2005 come with whole new application suite for example, Web Site template , web application template and mix mode of Ajax templates user had options to chose between many things. I personally used IIS and File System web site and web applications (File System web run on Vs integrated vs development web server ) in windows XP. I have recently moved to windows vista and and VS2008 Team System. I found some interesting stuff regarding windows vista and vs2008 that I thought need little share with the community (might help some one).

Web site in VS2008 on windows vista that run on IIS

image

I wanted to create a web site in IIS so I opened vs2008 selected ASP.net "Web Site" project template and Choose Local IIS but I found a strange message and unable to proceed to create a virtual directory from the wizard. I didn't read the message carefully, I thought my IIS is not installed properly or my IIS is not running. I opened my IIS administration MMC from administrator tool and found that IIS is up and running well, then I got confused and performed the same site creation operation again. This time when the Local Internet Information Server tab got selected I read the message carefully and it says how to create web site from vs2008, and it says I got to run vs2008 with "Run as administrator" :)

image

I closed my IDE and opened IDE from start menu with "Run as administrator" options selected from right click menu and performed the same operation again, this time every thing worked just okay :).

image

Web app in VS2008 on windows vista that run on IIS

While creating a "web application" project (which is created via choosing new project, rather than new web site from File->New menu) user do not have any option to select between File system or IIS hosted project in project creation wizard. By Default a File System based web application is created for the user. Just follow the normal procedure to create a web application, after web application creation is completed select the project properties. When the project properties window appear select the Tab named "Web*". You will see in web tab by default "Use Visual Studio Development Server" option is selected. change it to "Use IIS Web Server" option. After that just click on the Create Virtual Directory button to finish the procedure. save the project and you are good to go.

image

Oh one more thing, for this operation, again you have to run IDE in Run as administrator mode.

Friday, December 7, 2007

Visual studio as database designer

Visual studio have now supports working with data extensively. I mean the feature was there from the beginning but how the UI and interaction is perfected. For instance lets say we don’t have any sql server 2000 database, or even no MSDE database. Not even the new express database that came with the default installation. Still we have the “filename.mdf” the file based SQL Express database support. and to work with that we only need visual studio to SQL Server management studio is necessary. All the purpose of normal developer work can be achieved by visual studio.

For instance create a mdf database. Then work on creating tables, views, store procedures, functions, and what not. Bellow I have provided a screen shot, that is been lunched right after you create a mdf file based database.

image

Visual also have some rich table creating and manipulate facilities. When we create a mdf file based db, it automatically creates a data connection for us in server explorer. Note that we can also connect to SQL server express, sql server, oracle , odbc and any database with a supported provider.

image

One key improvement is that not only we can create and modify any kind of database object in visual studio but also we can attach sql debugger to step in to store procedure to to see what is happening inside the query.

image

There are many more database related feature in visual studio and looks like its moving towards perfection as a IDE. But I have a concern though, when the IDE will be perfect obviously It would be performance issue, the big guys from MS should look after it.