Silverlight 4 ContextMenu using ContextMenuService

17 04 2010

Silverlight 4 now support right click.

Now you can view your own ContextMenu.

Silverlight 4 toolkit have ContextMenu control. You can easily create your own ContextMenu which contains-

-MenuItem with Icon

-Menu Separator

Silverlight 4 Toolkit ContextMenu

You can use Silverlight toolkit ContextMenuService which will handle the event and positioning of the ContextMenu

All you need the reference of the namespace like below:
xmlns:controlsInputToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"

Now you can define the ContextMenuService and the ContextMenu like below:

    <controlsInputToolkit:ContextMenuService.ContextMenu>
        <controlsInputToolkit:ContextMenu
            Height="100"
            Name="contextMenu1"
            Width="200">
            <controlsInputToolkit:MenuItem
                x:Name="MenuItem1"
                Header="MenuItem-1"
                Click="MenuItem1_Click"
                IsEnabled="True">
                <controlsInputToolkit:MenuItem.Icon>
                    <Image
                        Height="25"
                        Width="25"
                        Source="Images/Silverlight.png"></Image>
                </controlsInputToolkit:MenuItem.Icon>
            </controlsInputToolkit:MenuItem>
            <controlsInputToolkit:MenuItem
                x:Name="MenuItem2"
                Header="MenuItem-2"
                Click="MenuItem2_Click"
                IsEnabled="True">
                <controlsInputToolkit:MenuItem.Icon>
                    <Image
                        Height="25"
                        Width="25"
                        Source="Images/Bird.png"></Image>
                </controlsInputToolkit:MenuItem.Icon>
            </controlsInputToolkit:MenuItem>
            <controlsInputToolkit:Separator />
            <controlsInputToolkit:MenuItem
                x:Name="MenuItem3"
                Header="MenuItem-3"
                Click="MenuItem3_Click"
                IsEnabled="True">
                <controlsInputToolkit:MenuItem.Icon>
                    <Image
                        Height="25"
                        Width="25"
                        Source="Images/logo.png"></Image>
                </controlsInputToolkit:MenuItem.Icon>
            </controlsInputToolkit:MenuItem>
        </controlsInputToolkit:ContextMenu>
    </controlsInputToolkit:ContextMenuService.ContextMenu>

In this sample MainPage is considered for right click.
Now in the code behind you need handled the right click down event for the MainPage (Hide the default one)  like below:

    public MainPage()
    {
        InitializeComponent();
        this.MouseRightButtonDown += new MouseButtonEventHandler(MainPage_MouseRightButtonDown);
    }
    void MainPage_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
    }

View Demo Here
Download Source Here





TIPS: Get actual width and height of an Image

4 04 2010

You can use ImageOpened event to get actual width and height of an Image like below:

        MyImage.ImageOpened += new EventHandler<RoutedEventArgs>(Image_ImageOpened);
    }
    void Image_ImageOpened(object sender, RoutedEventArgs e)
    {
        Image img = (Image)sender;
        BitmapImage bi = (BitmapImage)img.Source;
        double width = bi.PixelWidth;
        double height = bi.PixelHeight;
    }




TIPS: Get an element from specific row and column of a Grid

1 04 2010

You can get an element from specific row and column of a Grid like below:

    public UIElement GetElement(int row, int column, Grid gridToSearch)
    {
        return gridToSearch.Children
            .Where(w => w.GetValue(Grid.RowProperty).Equals(row)
                     && w.GetValue(Grid.ColumnProperty).Equals(column))
            .FirstOrDefault();
    }




My VisualTreeHelper search the visual tree

1 03 2010

VisualTreeHelper class is very useful so far i found.

The VisualTreeHelper type exposes the foure members.

Check here:

http://msdn.microsoft.com/en-us/library/system.windows.media.visualtreehelper_members%28VS.95%29.aspx

We could use VisualTreeHelper and write another two method which i found very useful like below:

SearchFrameworkElement – Get the child FrameworkElement with a given name from the visual tree of a parent FrameworkElement.

GetAllChildFrameworkElement – Get All Child FrameworkElement of given FrameworkElement

Source Code below:

public class MyVisualTreeHelper
{
    /// <summary>
    /// Get the child FrameworkElement with a given name
    /// from the visual tree of a parent FrameworkElement.
    /// </summary>
    /// <param name="parentFrameworkElement">Parent FrameworkElement</param>
    /// <param name="childFrameworkElementNameToSearch">Child FrameworkElement name</param>
    /// <returns>Child FrameworkElement with a given name</returns>
    public static FrameworkElement SearchFrameworkElement(FrameworkElement parentFrameworkElement, string childFrameworkElementNameToSearch)
    {
        FrameworkElement childFrameworkElementFound = null;
        SearchFrameworkElement(parentFrameworkElement, ref childFrameworkElementFound, childFrameworkElementNameToSearch);
        return childFrameworkElementFound;
    }
    /// <summary>
    /// Get All Child FrameworkElement of given FrameworkElement
    ///</summary>
    /// <param name="parentElement">Parent FrameworkElement whose child FrameworkElement's will be searched</param>
    /// <returns>List of Child FrameworkElement</returns>
    public static List<FrameworkElement> GetAllChildFrameworkElement(FrameworkElement parentElement)
    {
        List<FrameworkElement> childFrameworkElementFound = new List<FrameworkElement>();
        SearchAllChildFrameworkElement(parentElement, childFrameworkElementFound);
        return childFrameworkElementFound;
    }
    //SearchFrameworkElement helper
    private static void SearchFrameworkElement(FrameworkElement parentFrameworkElement, ref FrameworkElement childFrameworkElementToFind, string childFrameworkElementName)
    {
        int childrenCount = VisualTreeHelper.GetChildrenCount(parentFrameworkElement);
        if (childrenCount > 0)
        {
            FrameworkElement childFrameworkElement = null;
            for (int i = 0; i < childrenCount; i++)
            {
                childFrameworkElement = (FrameworkElement)VisualTreeHelper.GetChild(parentFrameworkElement, i);
                if (childFrameworkElement != null && childFrameworkElement.Name.Equals(childFrameworkElementName))
                {
                    childFrameworkElementToFind = childFrameworkElement;
                    return;
                }
                SearchFrameworkElement(childFrameworkElement, ref childFrameworkElementToFind, childFrameworkElementName);
            }
        }
    }
    //GetAllChildFrameworkElement helper
    private static void SearchAllChildFrameworkElement(FrameworkElement parentFrameworkElement, List<FrameworkElement> allChildFrameworkElement)
    {
        int childrenCount = VisualTreeHelper.GetChildrenCount(parentFrameworkElement);
        if (childrenCount > 0)
        {
            for (int i = 0; i < childrenCount; i++)
            {
                FrameworkElement childFrameworkElement = (FrameworkElement)VisualTreeHelper.GetChild(parentFrameworkElement, i);
                allChildFrameworkElement.Add(childFrameworkElement);
                SearchAllChildFrameworkElement(childFrameworkElement, allChildFrameworkElement);
            }
        }
    }
}




XML to TreeView HierarchicalDataTemplate in Silverlight3 toolkit

28 02 2010

XML:

<?xml version="1.0" encoding="utf-8"?>
<Composite>
  <Folder Name="1">
    <Folder Name="1.1">
      <Folder Name="1.1.1">
        <Folder Name="1.1.1.1">
          <File Name="file1"></File>
        </Folder >
      </Folder >
    </Folder >
  </Folder>
  <Folder Name="f2">
    <Folder Name="f2">
      <File Name="file21"></File>
      <File Name="file22"></File>
    </Folder>
  </Folder>
  <Folder Name="f">
    <File Name="file31"></File>
    <File Name="file32"></File>
  </Folder>
</Composite>

First define your data structure.

Load the the structure from XML. You need recursion to load the folders.

In the Silverlight application:

1. Use Silverlight Toolkit TreeView control

2. Define HierarchicalDataTemplate

3. Set the item source

Check the sample below :

    <!--xmlns:common="clr-namespace:System.Windows;assembly=System.Windows.Controls"-->
    <Grid x:Name="LayoutRoot"
          Background="White">
        <Grid.Resources>
            <common:HierarchicalDataTemplate x:Key="NodeTemplate"
                                             ItemsSource="{Binding Folders}">
                <Grid Width="Auto">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock Text="{Binding Name}">
                    </TextBlock>
                    <ListBox Grid.Row="1"
                             ItemsSource="{Binding FileNames}"></ListBox>
                </Grid>
            </common:HierarchicalDataTemplate>
        </Grid.Resources>

        <controls:TreeView x:Name="tvFolders"
                           BorderThickness="0"
                           ItemTemplate="{StaticResource NodeTemplate}">
        </controls:TreeView>

    </Grid>
    public partial class TreeViewSample : UserControl
    {
        public TreeViewSample()
        {
            InitializeComponent();

            tvFolders.ItemsSource = this.LoadFromXML();

        }

        public List<Folder> LoadFromXML()
        {
            XElement elementLoaded = XElement.Load("XMLFile1.xml");
            List<Folder> folders = new List<Folder>();
            this.LoadFolders(elementLoaded.Elements("Folder").ToList(), folders);

            return folders;
        }

        public void LoadFolders(List<XElement> elmFolders, List<Folder> folders)
        {
            foreach (var item in elmFolders)
            {
                var folder = new Folder
                {
                    Name = item.Attribute("Name").Value,
                    Folders = new List<Folder>(),
                    FileNames = item.Elements("File").Select(s => s.Attribute("Name").Value).ToList()
                };
                folders.Add(folder);
                this.LoadFolders(item.Elements("Folder").ToList(), folder.Folders);
            }
        }
    }

    public class Folder
    {
        public string Name { get; set; }
        public List<Folder> Folders { get; set; }
        public List<string> FileNames { get; set; }
    }




Silverlight – Converting text / Type to an object

28 02 2010

Problem:

Let’s say you have a series of ChildWindows that each show some data. e.g Add/Edit Customer, Add/Edit Vendor and etc.

Each ChildWindow has a name e.g. AddCustomer, AddVendor.

And you also have a series of Hyperlinks that are used to show these childwindows. Suppose you want to do is to have “one” method that all these Hyperlinks call to open their related childwindow. Each Hyperlink tag is holding the same name of the ChildWindow, i.e. AddCustomer, AddVendor as above.

Solution:

You can use Activator.CreateInstance which create object from type

    string childWindowTypeName = "ChildWindow1";//hyperlink.Tag.ToString()
    string nameSpace = this.GetType().Namespace;

    Type type = Type.GetType(string.Format("{0}.{1}", nameSpace, childWindowTypeName));

    ChildWindow c = Activator.CreateInstance(type) as ChildWindow;
    c.Show();




Adding DataGrid RowDetailsTemplate or TemplateColumn in Code Bhind

27 01 2010

Create a DataTemplate structure in resources.

Then we can  load the DataTemplete and set it to DataGrid rowDetailsTemplate /TemplateColumn

We can use a StackPanel/Grid inside the DataTemplate and set load event on StackPanel to add new children at runtime.

Example below:

XAML:

<UserControl.Resources>
<DataTemplate x:Key=“rowDT”>
<StackPanel Loaded=“StackPanel_Loaded” Orientation=“Horizontal” Background=“White”>

</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name=“LayoutRoot” Background=“Wheat”>
<data:DataGrid x:Name=“myDataGrid” AutoGenerateColumns=“False”>
</data:DataGrid>
</Grid>

Code Behind For RowDetailsTemplate:

        public Page()
        {
            InitializeComponent();

            var rowDetailsTemplate = (DataTemplate)this.Resources["rowDT"];
            myDataGrid.RowDetailsTemplate = rowDetailsTemplate;
            myDataGrid.ItemsSource = GridData.GetGridData();
        }

        private void StackPanel_Loaded(object sender, RoutedEventArgs e)
        {
            var templateChildPanel = sender as StackPanel;
            var detailTextBlock = new TextBlock
            {
                Width = 350,
                TextWrapping = TextWrapping.Wrap,
                Text = "I am Amyo Kabir"
            };

            //If you need binding
            //var dataBinding = new Binding("DetailsText");
            //dataBinding.Mode = BindingMode.TwoWay;
            //detailTextBlock.SetBinding(TextBlock.TextProperty, dataBinding);
            templateChildPanel.Children.Add(detailTextBlock);
        }

Code Behind For TemplateColumn:

        public Page()
        {
            InitializeComponent();

            var cellTemplate = (DataTemplate)this.Resources["rowDT"];

            var dataGridTemplateColumn = new DataGridTemplateColumn();
            dataGridTemplateColumn.Header = "Run Time Column";
            dataGridTemplateColumn.CellTemplate = cellTemplate;

            myDataGrid.Columns.Add(dataGridTemplateColumn);
        }

        private void StackPanel_Loaded(object sender, RoutedEventArgs e)
        {
            var templateChildPanel = sender as StackPanel;
            var detailTextBlock = new TextBlock
            {
                Width = 350,
                TextWrapping = TextWrapping.Wrap,
                Text = "I am Amyo Kabir"
            };

            //If you need binding
            //var dataBinding = new Binding("DetailsText");
            //dataBinding.Mode = BindingMode.TwoWay;
            //detailTextBlock.SetBinding(TextBlock.TextProperty, dataBinding);
            templateChildPanel.Children.Add(detailTextBlock);
        }