Archive
DataGridRow and Tooltip
We can use Popup to display a tooltip at the row level in the datagrid
Here is sample code
<UserControl x:Class=”slapp1a.Page”
xmlns=”http://schemas.microsoft.com/client/2007“
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“
xmlns:data=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”
Width=”600″ Height=”600″>
<UserControl.Resources>
<DataTemplate x:Key=”dt”>
<StackPanel Orientation=”Horizontal”>
<TextBlock Text=”This is a tooltip for the Row with content : “></TextBlock>
<TextBlock Text=”{Binding}”></TextBlock>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name=”LayoutRoot” Background=”White”>
<data:DataGrid x:Name=”dataGrid1″
Height=”400″
Width=”450″
Margin=”0,5,0,10″
AutoGenerateColumns=”True” />
<Popup x:Name=”myPopup”>
<ContentControl x:Name=”PopupContent” ContentTemplate=”{StaticResource dt}”></ContentControl>
</Popup>
</Grid>
</UserControl>
and in codebehind. all we are doing is handling the PreparingRow event to attach evenhandlers for MouseEvents, where we position the popup and set the content for the contentcontrol in the popup.
Did not try it, but we could change it use storyboards to introduce some delay before showing the tooltip and ofcourse customize the appearance
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
dataGrid1.ItemsSource = new string[] { “data 1″, “data 2″ };
dataGrid1.PreparingRow += new EventHandler<DataGridRowEventArgs>(dataGrid1_PreparingRow);
} void dataGrid1_PreparingRow(object sender, DataGridRowEventArgs e)
{
e.Row.MouseEnter += new MouseEventHandler(Row_MouseEnter);
e.Row.MouseLeave += new MouseEventHandler(Row_MouseLeave);
}
void Row_MouseLeave(object sender, MouseEventArgs e)
{
myPopup.IsOpen = false;
}
void Row_MouseEnter(object sender, MouseEventArgs e)
{
PopupContent.Content = (sender as DataGridRow).DataContext;
Point p = e.GetPosition(null);
myPopup.HorizontalOffset = p.X;
myPopup.VerticalOffset = p.Y;
myPopup.IsOpen = true;
}
}
Storyboard and DataTemplate
This post shows animating Item(s) in datatemplate
<UserControl x:Class=”SilverlightApplication9.Page”
xmlns=”http://schemas.microsoft.com/client/2007“
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“
xmlns:data=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”
Width=”600″ Height=”600″>
<UserControl.Resources>
<Storyboard x:Key=”sbMouseEnter”
Storyboard.TargetProperty=”FontSize”>
<DoubleAnimation From=”10″ To=”12″ Duration=”0:0:1″ />
</Storyboard>
<Storyboard x:Key=”sbMouseLeave”
Storyboard.TargetProperty=”FontSize”>
<DoubleAnimation From=”12″ To=”10″ Duration=”0:0:1″ />
</Storyboard>
<DataTemplate x:Key=”dt”>
<TextBlock Padding=”5,0,5,0″ FontSize=”10″
MouseEnter=”TextBlock_MouseEnter”
MouseLeave=”TextBlock_MouseLeave”
Text=”{Binding FirstName}”/>
</DataTemplate>
</UserControl.Resources>
<Canvas Width=”500″ Height=”500″>
<data:DataGrid x:Name=”dataGrid5″
Height=”100″ Width=”450″ Margin=”0,5,0,10″ >
<data:DataGrid.Columns>
<data:DataGridTemplateColumn Header=”Name”
CellTemplate=”{StaticResource dt}”>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
<ListBox Margin=”150″ Height=”100″ Width=”200″
x:Name=”list1″ ItemTemplate=”{StaticResource dt}”></ListBox>
</Canvas>
</UserControl>
we create 2 storyboards without the target property set, and datatemplate, we use the same datatemplate in datagrid as well as listbox and when the mouseenter and mouseleave events we could do some animation, for this sample we will do fontsize
we bind the controls to some data and we handle the mouse events on the textbox to begin the storyboard after setting the targetproperty
List<Customer> customers = new List<Customer>();
customers.Add(new Customer { FirstName = “John”, LastName = “Doe” });
customers.Add(new Customer { FirstName = “Jane”, LastName = “Doe” });
list1.ItemsSource = dataGrid5.ItemsSource = customers;
{
Storyboard sb = Resources["sbMouseEnter"] as Storyboard;
Storyboard.SetTarget(sb.Children[0],(sender as TextBlock));
sb.Begin();
}
{
Storyboard sb = Resources["sbMouseLeave"] as Storyboard;
Storyboard.SetTarget(sb.Children[0], (sender as TextBlock));
sb.Begin();
}
Drag and Drop in Silverlight
Let’s do some drag & drop of Items between listboxes. The same thing could be used for rearranging items in a control(say listbox).
we can even show what item is getting dragged around
you can see a demo here
(Note: updated code if you drag and drop between listboxes it should be fine. Error checking is not there, it will blowup if you click in the empty space in the listbox and mouseup and down on a item without dragging, need to fix those issues)
In the sample, I am using 3 listboxes each having different Itemtemplates
for the HitTest to work the listboxes have to be given some Background otherwise HitTest wont work
we are going to use the same events MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove events
the example here is using all listboxes, so the code is going to refer to listboxes
In XAML we drop a PopUp control with a ContentControl as child and set the opacity to .5, just to give it some effect
We start the DragDrop when the mouseleftbuttondown event is raised, we do a hittest and see if it is a listbox, If so start DragDrop
we are assuming that all the listboxes will have ItemTemplates defined
void StartDragDrop(ListBox sender,MouseEventArgs e)
{
DataTemplate dt = sender.ItemTemplate as DataTemplate;
dragSource = sender;
popupContent.Content = sender.SelectedItem;
popupContent.ContentTemplate = dt;
popup1.CaptureMouse();
captured = true;
mouseVerticalPosition = e.GetPosition(null).Y;
mouseHorizontalPosition = e.GetPosition(null).X;
popup1.HorizontalOffset = mouseHorizontalPosition;
popup1.VerticalOffset = mouseVerticalPosition;
}
We are getting the Datatemplate of the listbox and SelectedItem of the listbox we are interested in and setting the content of the ContentControl in the PopUp to the selectedItem of the ListBox.
Set the ContentTemplate property of the ContentControl to this DataTemplate.
Make sure we capture the mouse
For positioning the popup we set the HorizontalOffset and VerticalOffset properties of the Popup Control we added in the XAML
when the mouse moves we are going to adjust the same properties(HorizontalOffset and VerticalOffset) of the Popup Control to reflect mouse movement
when the MouseLeftButtonUp is raised we do a hitTest again to see the Destination(listBox)
void Page_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
List elements = (List)this.HitTest(e.GetPosition(null));
for(int i=0;i<elements.Count;i++){
ListBox lb = elements[i] as ListBox;
if (lb != null){
(lb.ItemsSource as ObservableCollection).Add(popupContent.Content as Customer);
(dragSource.ItemsSource as ObservableCollection).Remove(popupContent.Content as Customer);
break;
}
}
captured = false;
popupContent.Content = null;
popupContent.ContentTemplate = null;
popup1.ReleaseMouseCapture();
mouseVerticalPosition = -1;
mouseHorizontalPosition = -1;}
Add and remove Items as necessary and we have to make sure we set the Content and ContentTemplate properties of the ContentControl in the Popup to null, release the mousecapture
download the updated source here
GroupBox
Here is a sample template for groupbox in silverlight (mostly from groupbox in WPF)
you can download the source here
Silverlight wizard
This sample shows how we can use modal dialog to create a wizard in silverlight which helps user through a series of steps.
when the user goes through all the steps data is returned to the page
see a demo( you will have to click once on demo link and click again on the file, until I figure out a better way)
you specify the Content of the wizard using wizard steps, the following snippet shows how we create a wizard
<UserControl x:Class=”WizardApp.ModalPage”
xmlns=”http://schemas.microsoft.com/client/2007“
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“
xmlns:local=”clr-namespace:WizardApp;assembly=WizardApp”
Width=”400″ Height=”300″>
<Border BorderBrush=”Beige” CornerRadius=”5″
BorderThickness=”4″>
<Grid x:Name=”LayoutRoot”
Background=”AliceBlue”>
<local:Wizard x:Name=”wz”
Margin=”5″>
<local:Wizard.Steps>
<local:WizardStep Header=”Personal”>
<Grid Margin=”10″>
<Grid.RowDefinitions>
<RowDefinition Height=”40″ />
<RowDefinition Height=”40″ />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”150″ />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text=”FirstName”
Margin=”2″></TextBlock>
<TextBox Grid.Column=”1″
Margin=”2″
Text=”{Binding FirstName, Mode=TwoWay}”></TextBox>
<TextBlock Grid.Row=”1″
Margin=”2″
Grid.Column=”0″
Text=”LastName”></TextBlock>
<TextBox Grid.Row=”1″
Margin=”2″
Grid.Column=”1″
Text=”{Binding LastName, Mode=TwoWay}”></TextBox>
</Grid>
</local:WizardStep>
…
</local:Wizard.Steps>
</local:Wizard>
</Grid>
</Border>
</UserControl>
In the sample we click the button to start the wizard
When the wizard opens first step if selected and content of the first step is displayed
we navigate between the steps using previous and next buttons and click finish in the last step
The Wizard step headers will be placed in a custom panel which spaces the headers of the steps to fill the width of the wizard
The data entered by the user in the wizard will be shown in the page
What this sample doesnt have
It doesnt do any validations
It doesnt have any styles
I did not add code to display the steps vertically
Wizard doesn’t have cancel button, to cancel the wizard and all the other user friendly features
You can download the sample
here
ModalDialog
Displaying a ModalDialog in Silverlight is simple, thanks to Karen Corby for providing a reusable class
you can download sample code for ModalDialog here
how to use it
copy the code for class into the project
Create a page(“ModalPage”) with the content we want to be displayed in ModalDialog
when it is time to display the dialog, all we need to do is add couple of lines of code
ModalDialog.Closed += new EventHandler<ModalDialogClosedEventArgs>(ModalDialog_Closed);
//”ModalPage” is the name of the page we created
ModalDialog.Show(new SolidColorBrush(Colors.LightGray), .5, new ModalPage());
void ModalDialog_Closed(object sender, ModalDialogClosedEventArgs e)
{
if (e.Result == DialogResult.OK)
//do something
else
//do something
}
Silverlight MasterPages
Someone in silverlight forums was looking for asp.net master page kind of functionality. Here is one way to do it
<Grid x:Name=”LayoutRoot” Background=”White”>
<Grid.RowDefinitions>
<RowDefinition Height=”50″></RowDefinition>
<RowDefinition Height=”*”></RowDefinition>
<RowDefinition Height=”50″></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Height=”50″ Grid.Row=”0″ Orientation=”Horizontal”>
<Button Click=”Button_Click” Height=”25″ Tag=”c1″ Content=”Content page 1″></Button>
<Button Click=”Button_Click” Height=”25″ Tag=”c2″ Margin=”10,0,0,0″ Content=”Content page 2″></Button>
<Button Click=”Button_Click” Height=”25″ Tag=”c3″ Margin=”10,0,0,0″ Content=”Content page 3″></Button>
</StackPanel>
<Grid Grid.Row=”1″ x:Name=”ContentArea”>
<ContentControl x:Name=”Container”></ContentControl>
</Grid>
<Canvas Grid.Row=”2″ Background=”MediumSlateBlue”>
<TextBlock Text=”This is footer” Margin=”100,5,100,5″></TextBlock>
</Canvas>
</Grid>
we define a grid with 3 rows the center row will take up all the space between the header row and footer row(top and bottom), when we need to change the content we are going to load the content into the ContentControl in Row 1 of the grid
private void Button_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
string loadContent = b.Tag.ToString();
switch (loadContent)
{
case “c1″:
this.Container.Content = new ContentPage1();
break;
case “c2″:
this.Container.Content = new ContentPage2();
break;
case “c3″:
this.Container.Content = new ContentPage3();
break;
}
}