Tuesday, August 10, 2010

Error while downloading .NET Framework 3.5 pre-requisite (.msp file) with a WPF project in ClickOnce

In my WPF XBAP application, I've been trying to deploy it into remote server (It contains public domain) and install an application using certificate authority installer pre-requisites (since my application is running in Full-Trust mode) and the .NET Framework 3.5 SP1. I have set option which should download all the pre-requisites from the same location as the application.  The application is published using Visual Studio 2008 Professional Edition. If .NET Framework 3.5 is already installed then the ClickOnce installation should works fine. Otherwise it should download the missing pre-requisites from the same location and install to the Client machine.

If you try to download the application on the clean XP machine, you might have been facing the following issue.

"An error occurred downloading the following resource:
http://hostname/sampleapp/DotNetFX35/dotNetFX20/aspnet.msp"

In order to avoiding this issue, you would have to add the MIME type of the .msp file to the IIS of hosting server. You can access the MIME types by going into your site's properties -> HTTP headers -> MIME types then click NEW and add an extension and MIME type.

Extension            :               .msp

MIME                  :               application/microsoftpatch

Extension            :               .msu

MIME                  :               application/microsoftupdate

Please refer this link for more details.
Hope it will help!!

Wednesday, June 2, 2010

How to add Watermark Text to TextBox and PasswordBox in WPF?

I had a requirement in my sample application to show the watermark text (Help text) in input TextBox and PasswordBox (like Win7 Style of authentication). After a few minutes of search through internet, I got lots of sample application for showing watermark text in TextBox. But I couldn't get a sample application for showing watermark text to the PasswordBox. Again I searched for PasswordBox and finally I got an idea from this forum post. 

Since the PasswordBox is a sealed class, you cannot inherit a custom class from PasswordBox. Also Password property is not a dependency property hence you cannot write triggers. Hence I have created a custom class with attached properties such as WatermarkText (for showing the help text about the box), IsMonitoring (for monitoring the input), TextLength (for finding the input text length) and HasText (an internal property which decides whether the watermark text needs to be shown in box or not). The following code and style will help you to achieve this functionality.

WaterMarkTextHelper class:-

public class WaterMarkTextHelper : DependencyObject
    {
        #region Attached Properties

        public static bool GetIsMonitoring(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsMonitoringProperty);
        }

        public static void SetIsMonitoring(DependencyObject obj, bool value)
        {
            obj.SetValue(IsMonitoringProperty, value);
        }

        public static readonly DependencyProperty IsMonitoringProperty =
            DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(WaterMarkTextHelper), new UIPropertyMetadata(false, OnIsMonitoringChanged));

        
        public static bool GetWatermarkText(DependencyObject obj)
        {
            return (bool)obj.GetValue(WatermarkTextProperty);
        }

        public static void SetWatermarkText(DependencyObject obj, string value)
        {
            obj.SetValue(WatermarkTextProperty, value);
        }

        public static readonly DependencyProperty WatermarkTextProperty =
            DependencyProperty.RegisterAttached("WatermarkText", typeof(string), typeof(WaterMarkTextHelper), new UIPropertyMetadata(string.Empty));

        
        public static int GetTextLength(DependencyObject obj)
        {
            return (int)obj.GetValue(TextLengthProperty);
        }

        public static void SetTextLength(DependencyObject obj, int value)
        {
            obj.SetValue(TextLengthProperty, value);

            if (value >= 1)
                obj.SetValue(HasTextProperty, true);
            else
                obj.SetValue(HasTextProperty, false);
        }

        public static readonly DependencyProperty TextLengthProperty =
            DependencyProperty.RegisterAttached("TextLength", typeof(int), typeof(WaterMarkTextHelper), new UIPropertyMetadata(0));

        #endregion

        #region Internal DependencyProperty

        public bool HasText
        {
            get { return (bool)GetValue(HasTextProperty); }
            set { SetValue(HasTextProperty, value); }
        }
        
        private static readonly DependencyProperty HasTextProperty =
            DependencyProperty.RegisterAttached("HasText", typeof(bool), typeof(WaterMarkTextHelper), new FrameworkPropertyMetadata(false));

        #endregion

        #region Implementation

        static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is TextBox)
            {
                TextBox txtBox = d as TextBox;

                if ((bool)e.NewValue)
                    txtBox.TextChanged += TextChanged;
                else
                    txtBox.TextChanged -= TextChanged;
            }
            else if (d is PasswordBox)
            {
                PasswordBox passBox = d as PasswordBox;

                if ((bool)e.NewValue)
                    passBox.PasswordChanged += PasswordChanged;
                else
                    passBox.PasswordChanged -= PasswordChanged;
            }
        }

        static void TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox txtBox = sender as TextBox;
            if (txtBox == null) return;
            SetTextLength(txtBox, txtBox.Text.Length);
        }

        static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            PasswordBox passBox = sender as PasswordBox;
            if (passBox == null) return;
            SetTextLength(passBox, passBox.Password.Length);
        }
        
        #endregion
    }

XAML Style:-
<Style TargetType="{x:Type PasswordBox}"> <Setter Property="local:WaterMarkTextHelper.IsMonitoring" Value="True"/> <Setter Property="local:WaterMarkTextHelper.WatermarkText" Value="Password" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type PasswordBox}"> <ControlTemplate.Resources> <Storyboard x:Key="enterGotFocus" > <DoubleAnimation Duration="0:0:0.4" To=".2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> <Storyboard x:Key="exitGotFocus" > <DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> <Storyboard x:Key="enterHasText" > <DoubleAnimation Duration="0:0:0.4" From=".2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> <Storyboard x:Key="exitHasText" > <DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> </ControlTemplate.Resources> <Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" Margin="1" /> <TextBlock x:Name="Message" FontStyle="Italic" Text="{TemplateBinding local:WaterMarkTextHelper.WatermarkText}" Foreground="Gray" IsHitTestVisible="False" FontFamily="Calibri" Opacity="0.8" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="6,0,0,0"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> <Trigger Property="IsEnabled" Value="True"> <Setter Property="Opacity" Value="1" TargetName="Bd"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="local:WaterMarkTextHelper.HasText" Value="False"/> <Condition Property="IsFocused" Value="True"/> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard Storyboard="{StaticResource enterGotFocus}"/> </MultiTrigger.EnterActions> <MultiTrigger.ExitActions> <BeginStoryboard Storyboard="{StaticResource exitGotFocus}"/> </MultiTrigger.ExitActions> </MultiTrigger> <Trigger Property="local:WaterMarkTextHelper.HasText" Value="True"> <Trigger.EnterActions> <BeginStoryboard Storyboard="{StaticResource enterHasText}"/> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard Storyboard="{StaticResource exitHasText}"/> </Trigger.ExitActions> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="WaterMarkTextBox" TargetType="{x:Type TextBox}"> <Setter Property="local:WaterMarkTextHelper.IsMonitoring" Value="True"/> <Setter Property="local:WaterMarkTextHelper.WatermarkText" Value="Username" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <ControlTemplate.Resources> <Storyboard x:Key="enterGotFocus" > <DoubleAnimation Duration="0:0:0.4" To=".2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> <Storyboard x:Key="exitGotFocus" > <DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> <Storyboard x:Key="enterHasText" > <DoubleAnimation Duration="0:0:0.4" From=".2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> <Storyboard x:Key="exitHasText" > <DoubleAnimation Duration="0:0:0.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Message"/> </Storyboard> </ControlTemplate.Resources> <Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" Margin="1" /> <TextBlock x:Name="Message" Text="{TemplateBinding local:WaterMarkTextHelper.WatermarkText}" FontStyle="Italic" Foreground="Gray" IsHitTestVisible="False" FontFamily="Calibri" Opacity="0.8" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="6,0,0,0"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="local:WaterMarkTextHelper.HasText" Value="False"/> <Condition Property="IsFocused" Value="True"/> </MultiTrigger.Conditions> <MultiTrigger.EnterActions> <BeginStoryboard Storyboard="{StaticResource enterGotFocus}"/> </MultiTrigger.EnterActions> <MultiTrigger.ExitActions> <BeginStoryboard Storyboard="{StaticResource exitGotFocus}"/> </MultiTrigger.ExitActions> </MultiTrigger> <Trigger Property="local:WaterMarkTextHelper.HasText" Value="True"> <Trigger.EnterActions> <BeginStoryboard Storyboard="{StaticResource enterHasText}"/> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard Storyboard="{StaticResource exitHasText}"/> </Trigger.ExitActions> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
Since the custom class contains attached properties, we can use these attached properties to any TextBox control in our application for showing Watermark. You just need to merge the “ResourceDictionary” which contains the Style of Textbox and then need to assign the Watermark text to the TextBox using “WatermarkText” attached property. The sample code is given below.
<Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Resource.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <GroupBox Header="Dial-up Setting" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1"> <StackPanel VerticalAlignment="Center"> <TextBox Height="25" Width="200" Margin="10" Style="{StaticResource WaterMarkTextBox}"/> <PasswordBox Height="25" Width="200" /> <TextBox Height="25" Width="200" Margin="10" Style="{StaticResource WaterMarkTextBox}" local:WaterMarkTextHelper.WatermarkText="Domain"/> </StackPanel> </GroupBox>

Sample Output:-



Put a comment if you have any questions. Happy coding.

Monday, May 31, 2010

STEPS FOR XBAP SAMPLE DEPLOYMENT

The following are the steps for deploying the XBAP samples.

1. VIRTUAL DIRECTORY CREATION IN IIS

Create a Virtual Directory in local machine with local path. Please use the following steps to do this.

I. Open Internet Information Services (IIS) Manager. (Start -> Run -> inetmgr.exe).
II. Navigate to (Machine name -> Sites -> Default Web Sites).
III. Right click on “Default Web Sites” and select “Add Application option”.



IV. It will open “Add Application” dialog box. From this dialog box, please enter the “Alias” and “Physical Path”. Then Click OK button.




V. It will create a “Virtual directory” with the name of “Sample” to the physical path of “E:\Work\SourceCode\Version\Project\Control”.


2. WORKING SAMPLE APPLICATION WITH VS IDE


We should always work with Admin mode for deploying the XBAP application since we don’t have rights to access IIS in non-admin mode. Open VS IDE in Admin mode.




3. DEPLOYING SAMPLE APPLICATION


I. Open the solution file.

II. Do necessary changes in the application and build it.

III. Once the build get succeeded then open the properties of “Sample” application.

IV. From the properties window, go to Signing tab and make sure that “Sign the ClickOnce manifests” check box is checked. If not, select the certificate key from the Certificate storage.



V. Then navigate to “Security” tab and make sure that “This is a full trust application” radio button is in checked condition. Normally XBAP applications are run within a security sandbox to prevent untrusted applications from controlling local system resources. (E.g. deleting local files). In order to access local file system, port access, bitmap effects, etc., you need to run your application in “Full trust” mode.




VI. After that, select “Publish” tab and enter the publish location (Both local path and internet path where we would like to Run the application) and publish version information.




VII. Before that, make sure that the files needed to include with the application along with the published folder. This can be achieved with help of “Application Files” dialog by clicking the “Application Files” button.




VIII. We need to mention the “Prerequisites” to run our application. This will be provided by using “Prerequisites” dialog.




IX. Then provide the publishing details which will be shown in the main “index.htm” page.




X. Once you complete all above steps, please use publish wizard and publish the sample application.

4. DEPLOYING AN APPLICATION TO THE REMOTE SERVER
 I. Since we already given the internet URL while publishing the project application, we need to create a sample virtual directory in “Remote server’s IIS”. It will make URL available over the internet.

II. Then place the sample application’s (XBAP application) files and folder from local machine to the remote server.

Monday, May 17, 2010

How to get the DependencyObject under the mouse cursor?

With help of VisualTreeHelper and its HitTest() methods, we can easily find the DependencyObject under the mouse cursor. Use the following code snippet to achieve this.

    List<DependencyObject> hitTestList = null;

    //Raised When Mouse is entered inside Panel
    private void Panel_MouseEnter(object sender, MouseEventArgs e)
    {
        hitTestList = new List<DependencyObject>();       

        Point pt = e.GetPosition(sender as IInputElement);       

        VisualTreeHelper.HitTest(
            sender as Visual, null,
            CollectAllVisuals_Callback,
            new PointHitTestParameters(pt));       

        hitTestList.Reverse();

        DependencyObject elementToFind = null;
        foreach (DependencyObject element in hitTestList)
        {
            if (element.GetType().Name.Equals("ElementToFind"))
            {
                elementToFind = element;
                // ...
                // ...
            }
        }
    }

    HitTestResultBehavior CollectAllVisuals_Callback(HitTestResult result)
    {
        if (result == null || result.VisualHit == null)
            return HitTestResultBehavior.Stop;

        hitTestList.Add(result.VisualHit);
        return HitTestResultBehavior.Continue;
    }

Drop me a comment if you have any queries.

Friday, May 14, 2010

How to load Bitmap image to Image object in WPF

I am doing an application (which I am converting Windows forms 2.0 application into WPF application for rich look) in WPF and I am need of the load the Image from an instance of a System.Drawing.Bitmap. Initially I was struggled to do this. After a few minutes of search in goggle, I found the following solution. With help of Imaging class, we can create a BitmapSource and assign the BitmapSource value to the Image. The following code will help you to do this.

    public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
    {
        BitmapSource bitmapSrc = null;
        var hBitmap = source.GetHbitmap();
        try
        {
            bitmapSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
        }
        catch (Win32Exception)
        {
            bitmapSrc = null;
        }  
        finally
        {
            NativeMethods.DeleteObject(hBitmap);
        }
        return bitmapSrc;
    }

    internal static class NativeMethods
    {
        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool DeleteObject(IntPtr hObject);
    }

Please check this link for more details.

Tuesday, May 4, 2010

How to close the whole application in WPF Browser based application (XBAP application)


In Windows based WPF application, there is an option to close the whole application using (Application.Current.ShutDown) statement. But the same statement is not working in Web based WPF application (perhaps it will close the application. But not close the IE browser – It showing with the blank inactive tab).  We have an option to close the application along with the IE window by using the following code,

    private void buttonClose_Click(object sender, RoutedEventArgs e)
    {
        WindowInteropHelper wih = new WindowInteropHelper(Application.Current.MainWindow);
        IntPtr ieHwnd = GetAncestor(wih.Handle, 2 /*GA_ROOT*/);
        PostMessage(ieHwnd, 0x10/*WM_CLOSE*/, IntPtr.Zero, IntPtr.Zero);
    }

    [DllImport("user32", ExactSpelling = true, CharSet = CharSet.Auto)]
    private static extern IntPtr GetAncestor(IntPtr hwnd, int flags);   

    [DllImport("user32", CharSet = CharSet.Auto)]
    private static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

Wednesday, April 28, 2010

How to find the visual parent or child element using VisualTreeHelper

VisualTreeHelper is very useful class which help us to find or drill-down element from the hosted container.

The following method will help you to find the visual parent element from the container.

    public static T FindVisualParent<T>(UIElement element) where T : UIElement
    {
        UIElement parent = element;
        while (parent != null)
        {
            T correctlyTyped = parent as T;
            if (correctlyTyped != null)
            {
                return correctlyTyped;
            }
            parent = VisualTreeHelper.GetParent(parent) as UIElement;
        }
        return null;
    }

The following method will help you to find the child element from the container.

    public static T FindChild<T>(DependencyObject parent)where T : DependencyObject
    {
        if (parent == null) return null;

        T childElement = null;
        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            T childType = child as T;
            if (childType == null)
            {
                childElement = FindChild<T>(child);
                if (childElement != null) break;
            }
            else
            {
                childElement = (T)child;
                break;
            }
        }
        return childElement;
    }