Blog of a Filipino Developer about C#, VB.NET, ASP.NET, Java, PHP, SQL Server, MySql and Oracle RSS 2.0
# Monday, March 09, 2009

Tooltips are great additions to any interface and in this article I'm going to show you how to attach a tooltip to control in Silverlight 2.

To start, let's assume that we have a button that we want to add a tooltip to:

[XAML]

<UserControl x:Class="KeithRull.Silverlight.CreatingTooltips.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="#FF1E238E">
        <Button Content="Hover over me!" 
                Height="20" 
                Width="100" Margin="30 40" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left">
                
        </Button>
    </Grid>
</UserControl>

[Rendered UI]

In order or us to attach a tooltip to our button we need to create a reference to the TooltipService.Tooltip inside the our button's XAML declaration. We also need to setup the Tooltip.Content to tell the compiler what to show when the user hover's to our button.

[XAML]

<UserControl x:Class="KeithRull.Silverlight.CreatingTooltips.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="#FF1E238E">
        <Button Content="Hover over me!" 
                Height="20" 
                Width="100" Margin="30 40" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left">
            <ToolTipService.ToolTip>
                <ToolTip>
                    <ToolTip.Content>
                        <TextBlock TextWrapping="Wrap">
                            Hooray! I'm alive!.
                        </TextBlock>
                    </ToolTip.Content>
                </ToolTip>
            </ToolTipService.ToolTip>
        </Button>
    </Grid>
</UserControl>

[Rendered UI (at runtime)]

The message "Hooray! I'm alive!" appeared when the user hovers over our button. We can also cutomize how our tooltip appears by adding more XAML elements in the Tooltip.Content property.

[XAML]

<UserControl x:Class="KeithRull.Silverlight.CreatingTooltips.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="#FF1E238E">
        <Button Content="Hover over me!" 
                Height="20" 
                Width="100" Margin="30 40" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left">
            <ToolTipService.ToolTip>
                <ToolTip Background="#FFFFFF" Width="150">
                    <ToolTip.Content>
                        <StackPanel>
                            <Image Source="images/silverlight.png" />
                            <TextBlock HorizontalAlignment="Right">
                                It rocks like a champ!
                            </TextBlock>
                        </StackPanel>    
                    </ToolTip.Content>
                </ToolTip>
            </ToolTipService.ToolTip>
        </Button>
    </Grid>
</UserControl>

[Rendered UI (at runtime)]

Another customization that you might want to do is specifying the HorizontalOffset and the VerticalOffset. This allows you to specify where the tooltip will appear in reference to your target control.

Monday, March 09, 2009 10:49:38 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Silverlight | Tutorial
# Wednesday, March 04, 2009

I just saw this twitter...

Sweeeeet!

Time to start polishing my ASP.NET MVC skills. I've played with ASP.NET MVC before but never had the chance to use it other than building small samples. I might be rusty but I know I'll have a great companion book in learning ASP.NET MVC 1.0 once Rob, Scott, Scott and Phil's upcoming book comes out.

Wednesday, March 04, 2009 1:00:26 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ASP.NET | Tech News and Issues | MVC
# Wednesday, February 25, 2009

A user a devpinoy.org posted a question on the forum section asking if there's a way to restrict files from being saved in a directory. I know you can do this via the FileSystemWatcher class so I quickly whipped my Visual Studio 2008 IDE and started building a prototype application to demonstrate the solution.

The first thing that you need to do is to set-up some key details on what we want to watch/monitor

private const string ALLOWED_FILE_EXTENSION = ".doc";
private const string DEFAULT_WATCH_FOLDER = @"E:\Test Folder\";

Next, the FileSystemWatcher specify what directory you want to monitor.

FileSystemWatcher watcher = new FileSystemWatcher(DEFAULT_WATCH_FOLDER);

After that you need to setup the notification filters on what type of filesystem changes you want to watch;

watcher.NotifyFilter = NotifyFilters.LastAccess |
                                    NotifyFilters.LastWrite |
                                    NotifyFilters.FileName |
                                    NotifyFilters.DirectoryName |
                                    NotifyFilters.CreationTime;

And finally, we need to set-up the FileSystem events you want our FileSystem. In this case, we only want to monitor Created and Renamed events.

watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);

Now, let's start coding our event handlers.

For our event handler, I decided to use one method that would handle both the Created and Rename event. Ideally you want to seperate this to into two different methods because you might want to handle the tow events differently but since all I want to do is to block files\folders that doesn't match my criteria i decided to handle them both using a single method called FileSystemHandler.

void watcher_Renamed(object sender, RenamedEventArgs e)
{
    FileSystemHandler(e.Name, e.FullPath);
}

void watcher_Created(object sender, FileSystemEventArgs e)
{
    FileSystemHandler(e.Name, e.FullPath);    
}

Below is the implementation detail for our FileSystemHandler method.

void FileSystemHandler(string name, string fullpath)
{
    try
    {
        //read the contents of our directory
        DirectoryInfo di = new DirectoryInfo(DEFAULT_WATCH_FOLDER);
        //get the filesysteminfo[] objects
        FileSystemInfo[] fileSystemInfoArray = di.GetFileSystemInfos();

        //there's always going to be one object matching this criteria all the time
        FileSystemInfo found = fileSystemInfoArray.Single(f => f.FullName.Equals(fullpath));

        //if it finds something
        if (found != null)
        {
            //cast the found object to directoryinfo
            DirectoryInfo d = found as DirectoryInfo;

            //if it's null it means it's a FileInfo object
            if (d == null)
            {
                //cast found to a fileinfo object
                FileInfo f = found as FileInfo;

                //delete the file if the extension doesn't match our desired/allowed extension
                if (!f.Extension.Equals(ALLOWED_FILE_EXTENSION))
                {
                    f.Delete();
                }
            }
            else
            {
                //directories are not allowed on this folder too!
                d.Delete(true);
            }
        }
    }
    catch
    {
        //let it sleep for 30 seconds
        Thread.Sleep(30000);

        //it failed so we need to try again recussively
        /*
            note: it's a good idea to set a retry limit here because if we don't 
            then the app will retry to infinity but i'll leave that up to you.
         */
        FileSystemHandler(name, fullpath);
    }
}

What the function above is doing is that it checks to see if the filesystem object that was created on the directory is either a file or a directory. If it is a directory, automatically delete it since we dont want any directory to be saved on our folder. If it is a file we need to check if it's extension matches the allowed file extension. If it matches the allowed extension we let it thru. If it doesn't we call the the Delete method on the FileInfo object to delete the file.

All we need to do now is to tell the watcher to start monitor our folder

watcher.EnableRaisingEvents = true;

Setting EnableRaisingEvents to true triggers our watcher to start monitoring the folder. Setting it to false will stop the watcher.

And we are done! Now we have an application that blocks saving or renaming of files in a folder that doesn't match the allowed file extension.

Below is the full listing of the code for the demo project I built for this article:

using System;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace KeithRull.FolderSpy
{
    public partial class MainForm : Form
    {
        private bool IsCurrentlyWatching = false;
        private const string ALLOWED_FILE_EXTENSION = ".doc";
        private const string DEFAULT_WATCH_FOLDER = @"E:\Test Folder\";
        FileSystemWatcher watcher;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            SetUpWatcher();
        }

        private void watchButton_Click(object sender, EventArgs e)
        {
            if (!IsCurrentlyWatching)
            {
                watchButton.Text = "Stop watching";
                IsCurrentlyWatching = true;

                //start the watcher
                watcher.EnableRaisingEvents = true;
            }
            else
            {
                watchButton.Text = "Start watching";
                IsCurrentlyWatching = false;

                //stop the watcher
                watcher.EnableRaisingEvents = false;
            }
        }

        void watcher_Renamed(object sender, RenamedEventArgs e)
        {
            FileSystemHandler(e.Name, e.FullPath);
        }

        void watcher_Created(object sender, FileSystemEventArgs e)
        {
            FileSystemHandler(e.Name, e.FullPath);    
        }

        void FileSystemHandler(string name, string fullpath)
        {
            try
            {
                //read the contents of our directory
                DirectoryInfo di = new DirectoryInfo(DEFAULT_WATCH_FOLDER);
                //get the filesysteminfo[] objects
                FileSystemInfo[] fileSystemInfoArray = di.GetFileSystemInfos();

                //there's always going to be one object matching this criteria all the time
                FileSystemInfo found = fileSystemInfoArray.Single(f => f.FullName.Equals(fullpath));

                //if it finds something
                if (found != null)
                {
                    //cast the found object to directoryinfo
                    DirectoryInfo d = found as DirectoryInfo;

                    //if it's null it means it's a FileInfo object
                    if (d == null)
                    {
                        //cast found to a fileinfo object
                        FileInfo f = found as FileInfo;

                        //delete the file if the extension doesn't match our desired/allowed extension
                        if (!f.Extension.Equals(ALLOWED_FILE_EXTENSION))
                        {
                            f.Delete();
                        }
                    }
                    else
                    {
                        //directories are not allowed on this folder too!
                        d.Delete(true);
                    }
                }
            }
            catch
            {
                //let it sleep for 30 seconds
                Thread.Sleep(30000);

                //it failed so we need to try again recussively
                /*
                    note: it's a good idea to set a retry limit here because if we don't 
                    then the app will retry to infinity but i'll leave that up to you.
                 */
                FileSystemHandler(name, fullpath);
            }
        }

        void SetUpWatcher()
        {
            watcher = new FileSystemWatcher(DEFAULT_WATCH_FOLDER);
            watcher.NotifyFilter = NotifyFilters.LastAccess |
                                    NotifyFilters.LastWrite |
                                    NotifyFilters.FileName |
                                    NotifyFilters.DirectoryName |
                                    NotifyFilters.CreationTime;
            watcher.Created += new FileSystemEventHandler(watcher_Created);
            watcher.Renamed += new RenamedEventHandler(watcher_Renamed);

        }
    }
}

As always, you can download the code for the complete project here: KeithRull.FolderSpy.zip (40.38 KB)

Wednesday, February 25, 2009 7:48:40 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Tuesday, February 24, 2009

Tuesday, February 24, 2009 5:44:09 PM (GMT Standard Time, UTC+00:00)  #    Comments [3] -
Family | Life | Pregnancy
Archive
<March 2009>
SunMonTueWedThuFriSat
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Keith Rull
Sign In
Statistics
Total Posts: 271
This Year: 0
This Month: 0
This Week: 0
Comments: 182
Themes
Pick a theme:
All Content © 2010, Keith Rull
DasBlog theme 'Business' created by Christoph De Baene (delarou)