Slider with Ticks
This is one of the samples I did sometime back for showing the ticks. The code is compiled with Silverlight 3 beta but should work in Silverlight 2 also without any changes

you can find the source here
This is one of the samples I did sometime back for showing the ticks. The code is compiled with Silverlight 3 beta but should work in Silverlight 2 also without any changes

you can find the source here
Lets say we have a chart like this

it kind of looks like too many lines and user doesnt have easy way to see the different trends or easily compare the different measures user wants.
Showing and hiding a particular series will be nice addition to charts to allow the user to pick and choose what to see. we want the user to be able to click the legenditem to toggle the display of the series.


we will start adding a style for the LegendItem, the original style looks like this
<Style TargetType=”charting:LegendItem”>
<Setter Property=”IsTabStop” Value=”False” />
<Setter Property=”Template”>
<Setter.Value>
<ControlTemplate TargetType=”charting:LegendItem”>
<StackPanel Orientation=”Horizontal”>
<Rectangle Width=”8″ Height=”8″ Fill=”{Binding Background}”
Stroke=”{Binding BorderBrush}” StrokeThickness=”1″ Margin=”0,0,3,0″ />
<datavis:Title Content=”{TemplateBinding Content}” />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and we specify the style on the LineSeries like this
<charting:LineSeries LegendItemStyle=”{StaticResource LegendItemStyle}” Title=”Total Visits”
IndependentValueBinding=”{Binding OrderDate}”
DependentValueBinding=”{Binding Visits}” />
As we want to provide a way for the user to toggle the visibility of the Series. we will re-style the LegendItem to use a CheckBox for this sample
<Style x:Key=”LegendItemStyle” TargetType=”charting:LegendItem”>
<Setter Property=”IsTabStop” Value=”False” />
<Setter Property=”Template”>
<Setter.Value>
<ControlTemplate TargetType=”charting:LegendItem”>
<CheckBox Click=”CheckBox_Click” Cursor=”Hand” IsChecked=”true”
Content=”{TemplateBinding Content}” Tag=”{TemplateBinding Content}”>
<CheckBox.Template>
<ControlTemplate TargetType=”CheckBox”>
<StackPanel Orientation=”Horizontal”>
<Rectangle Width=”8″ Height=”8″ Fill=”{Binding Background}” Stroke=”{Binding BorderBrush}”
StrokeThickness=”1″ Margin=”0,0,3,0″ />
<datavis:Title Content=”{TemplateBinding Content}” />
</StackPanel>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(After posting I realized that instead of binding again to Tag we could base our condition on the content itself. Too lazy to change the code now)
To start with, we want all the series to be shown so we set the IsChecked property to “true”.
we added a click handler also to checkbox in which we are going to check the IsChecked property and decide if we want the series to be shown or hidden
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (sender as CheckBox);
LineSeries ls = chart1.Series.Cast
().Where(s => s.Title.ToString() == chk.Tag.ToString()).ElementAtOrDefault(0);
if (chk.IsChecked.Value)
chk.Opacity = ls.Opacity = 1;
else
{
chk.Opacity = 0.5;
ls.Opacity = 0;
}
}
PreparingCellForEdit event is useful when we want to customize/change the behaviour of the editing element based on some condition
lets say we have have
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
}
and the following XAML
<data:DataGrid x:Name=”datagrid1″ ItemsSource=”{Binding}” AutoGenerateColumns=”False”>
<data:DataGrid.Columns>
<data:DataGridTextColumn Binding=”{Binding ID}” IsReadOnly=”True” />
<data:DataGridTemplateColumn Header=”Name”
>
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text=”{Binding Name}”/>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text=”{Binding Name}” />
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
for (int i = 0; i < 10; i++)
persons.Add(new Person {ID=i, Name=”Person..”+ i.ToString() });
let’s say we want to disable editing of person whose id % 2 == 0
Here is what we can do
attach an event handler
datagrid1.PreparingCellForEdit += new EventHandler<DataGridPreparingCellForEditEventArgs>(datagrid1_PreparingCellForEdit);
In the event handler, get the datacontext, check for our condition, if it matches and if the column is what we are interested in, get the editing element (can be anything), in this case it is TextBox and set properties
void datagrid1_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
Person p = e.Row.DataContext as Person;
if (p.ID % 2 == 0)
{
if (e.Column.DisplayIndex == 1)
{
TextBox textBox = (e.EditingElement as TextBox);
textBox.IsReadOnly = true;
textBox.Background = new SolidColorBrush(Colors.Gray);
}
}
}
I was working with charts and ended up with something like this. it is not that clear to see the date and value. The data points look crowded. we could obviously increase the width of the chart, provide an useful tooltip so we could get better understanding of the data.

because of any number of reasons both of the options might not be suitable. more over the chart doesnt have any interactivity. I wanted to add the functionality of user being able to select the range of dates and chart would reflect that. we could easily acheive that using some controls to filter the date ranges etc. but here is what I came up with.
You can see a demo here.


you ctrl+click and drag on the chart(Plot Area) to select the range we want to focus on and when the mousebutton is up, the chart is drawn for the range selected. To undo the zoom and go back to original display of the chart, just click on the chart(Plot Area).
you can download the code from here
I came across a forum post in silverlight forums looking for a way to get markers in a linechart. I wanted to try it myself.
This is the end result. As the points are random, you might have to hit refresh, in case you dont see the lines.

I changed the template to include a canvas
<ControlTemplate TargetType=”charting:Chart”>
<Border Background=”{TemplateBinding Background}”
BorderBrush=”{TemplateBinding BorderBrush}”
BorderThickness=”{TemplateBinding BorderThickness}”
Padding=”10″>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto” />
<RowDefinition Height=”*” />
</Grid.RowDefinitions>
<datavis:Title Content=”{TemplateBinding Title}”
Style=”{TemplateBinding TitleStyle}” />
<!– Use a nested Grid to avoid possible clipping behavior resulting from ColumnSpan+Width=Auto –>
<Grid Grid.Row=”1″
Margin=”0,15,0,15″>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”*” />
<ColumnDefinition Width=”Auto” />
</Grid.ColumnDefinitions>
<datavis:Legend x:Name=”Legend”
Title=”{TemplateBinding LegendTitle}”
Style=”{TemplateBinding LegendStyle}”
Grid.Column=”1″ />
<Grid x:Name=”ChartArea”
Style=”{TemplateBinding ChartAreaStyle}”>
<Grid x:Name=”PlotArea”
Style=”{TemplateBinding PlotAreaStyle}”>
<Grid x:Name=”GridLinesContainer” />
<Grid x:Name=”SeriesContainer”>
</Grid>
<Border BorderBrush=”#FF919191″
BorderThickness=”1″ />
<Canvas Background=”Transparent”
x:Name=”c1″></Canvas>
</Grid>
</Grid>
</Grid>
</Grid>
</Border>
</ControlTemplate>
and in the code behind once we have the chart rendered . In the Layout updated method of the chart. I call the following function. which adds the markers
void Highlight(List<Order> orderList)
{
LineSeries ls = this.chart1.Series[0] as LineSeries;
Grid plotArea = chart1.GetChildrenByType<Grid>().Where(g => g.Name == “PlotArea”).SingleOrDefault<Grid>();
Canvas c1 = chart1.GetChildrenByType<Canvas>().Where(c => c.Name == “c1″).SingleOrDefault<Canvas>();
foreach (Order o in orderList)
{
Point p = ls.Points[orders.IndexOf(o)];
Line ln = new Line();
ln.Stroke = new SolidColorBrush(Colors.Black);
ln.StrokeThickness = 1.0;
DoubleCollection dashCollection = new DoubleCollection();
dashCollection.Add(2);
dashCollection.Add(4);
ln.StrokeDashArray = dashCollection;
ln.X1 = p.X;
ln.X2 = p.X;
ln.Y1 = -10.0;
ln.Y2 = plotArea.ActualHeight;
TextBlock txt = new TextBlock();
txt.Text = o.OrderDate.ToShortDateString();
txt.Foreground = new SolidColorBrush(Colors.Blue);
Grid chartArea = plotArea.Parent as Grid;
txt.SetValue(Canvas.LeftProperty, ln.X1 + 5.0);
txt.SetValue(Canvas.TopProperty, ln.Y1 – 10);
c1.Children.Add(txt);
c1.Children.Add(ln);
}
}
you can download the sample here
I started playing with live framework bits and learning a little bit. I created a silverlight MEWA.
The creation of silverlight MEWA is no different for the most part. So I wanted to work with Feeds, entries and resources
I have some samples that I have done previously. What I wanted to do is to store the XAP file, Title of the sample and some description in the entries and load the XAP file of the selected sample directly by reading the resource
SO I created a Silverlight MEWA in VisualStudio. with some basic UI with listBox to hold the list of samples and Contentcontrol to display the selected sample
For storing the data I created a feed like this after getting loading the MeshObjects
LiveOperatingEnvironment loe;
loe = new LiveOperatingEnvironment();
NetworkCredential creds = new NetworkCredential(“hotmail id”,”password”);
loe.Connect(creds);
DataFeed samples = new DataFeed(“Samples”);
loe.Mesh.MeshObjects.Entries.Where(q => q.Resource.Title == “Sample SL MEWA”).Single().DataFeeds.Add(ref samples);
Once I created a feed, I had to add some entries(1 for each sample)
//feed is the variable whch holds a reference to the feed I added
DataEntry entry = feed.DataEntries.Add(File.OpenRead(XAP filename), “ExtendedAutoCompleteBox”);
entry.Resource.SetUserData<XapData>(new XapData { Description = “This sample shows an extended Auto completebox to select multiple items”, MainDll =”Name of the dll”, StartPage = “Page”, Title = “ExtAutoCompleteBox” });
entry.Update();
feed.DataEntries.Add(ref entry);
feed.Update();
XAPData is another class I added which holds the different properties I want to access for the sample
public class XapData
{
public string StartPage { get; set; }
public string MainDll { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
That’s all for setting up the data to be used in the application
Now back in the Silverlight MEWA, After the MeshApp is loaded we will have access to the feeds and entries. So in the MeshAppLoaded eventhandler. I added a SelectionChanged event handler for the ListBox and set the ItemsSource of the listbox to be the list of entries
listSamples.SelectionChanged += new SelectionChangedEventHandler(listSamples_SelectionChanged);
DataFeed feed = meshApp.DataFeeds.Entries.First();
listSamples.ItemsSource = feed.DataEntries.Entries.ToList();
In the SelectionChanged eventhandler, we get the selected DataEntry, get the corresponding data we stored for the sample and Load the XAP file from the MediaResource
void listSamples_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems != null && e.AddedItems.Count > 0)
{
entry = e.AddedItems[0] as DataEntry;
entry.Load();
selectedItemData = entry.Resource.GetUserData<XapData>();
entry.ReadMediaResourceCompleted += new EventHandler<MediaResourceAsyncEventArgs>(entry_ReadMediaResourceCompleted);
entry.ReadMediaResourceAsync(stream);
}
Once the Resource(XAP file in this sample) is loaded, we load all the dlls in the XAP file and create an instance of the startpage for the sample
void entry_ReadMediaResourceCompleted(object sender, MediaResourceAsyncEventArgs e)
{
stream.Seek(0, SeekOrigin.Begin);
string appManifest = new StreamReader(Application.GetResourceStream(new StreamResourceInfo(stream, null), new Uri(“AppManifest.xaml”, UriKind.Relative)).Stream).ReadToEnd();
Assembly asm = null;
XElement deploymentRoot = XDocument.Parse(appManifest).Root;
List<XElement> deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
select assemblyParts).ToList();
Assembly MyAssembly = null;
foreach (XElement xElement in deploymentParts)
{
string source = xElement.Attribute(“Source”).Value;
AssemblyPart asmPart = new AssemblyPart();
StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(e.Result, “application/binary”), new Uri(source, UriKind.Relative));
if (source.EndsWith(“dll”)))
{
asm = asmPart.Load(streamInfo.Stream);
if (source == selectedItemData.MainDll)
MyAssembly = asm;
}
}
UIElement ele = MyAssembly.CreateInstance(selectedItemData.StartPage) as UIElement;
SampleContent.Content = ele;
}
}

As the Data is stored in the sample itself, I need to share the instance of this sample. if any one is interested in sharing their sample or want to see this sample, I can send an invite if you leave a comment.
I like the AutoComplete feature for email addresses in hotmail, we get suggestions for any number of email addresses when we start typing. With AutoCompleteBox we get one.
Here is my attempt to implement that feature extending AutoCompleteBox.
I defined a property called ‘ExtText’ instead of overriding the Text property
we will start using the control by declaring like this
<local:ExtAutoCompleteBox Margin=”25″ TextBoxStyle=”{StaticResource textboxStyle}”
x:Name=”eacb”
MinimumPrefixLength=”1″ />
I had to style the TextBox to remove some borders and adjust BorderThickness properties. this style is in Page.xaml and in the codebehind set the ItemsSource Property to an array of string values. once we start typing we get the popup with suggestions like below

After we make a selection, we get the word displayed similar to what hotmail does, you will be able to remove the item by clicking the ‘x’. and the cursor will move to the end. The button is just to get a message of all the selected words seperated by ‘;’



you can download the code here
When we want to display/edit date values in DataGrid, we could add a templatecolumn add a TextBlock to the CellTemplate and DatePicker to CellEditingTemplate. but that gets repetitive, if we are doing the same in multiple places
we can create this custom column by inheriting from DataGridBoundColumn and overriding few methods
Here is the minimal code to create a DataGridDateColumn
public class DataGridDateColumn : DataGridBoundColumn
{
public string DateFormat { get; set; }
protected override void CancelCellEdit(FrameworkElement editingElement, object uneditedValue)
{
DatePicker dp = editingElement as DatePicker;
if (dp != null)
{
dp.SelectedDate = DateTime.Parse(uneditedValue.ToString());
}
}
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
DatePicker dp = new DatePicker();
Binding b = new Binding();
b.Path = this.Binding.Path;
b.Source = this.Binding.Source;
if (DateFormat != null)
{
DateTimeConverter dtc = new DateTimeConverter();
b.Converter = dtc;
b.ConverterParameter = DateFormat;
}
dp.SetBinding(DatePicker.SelectedDateProperty, this.Binding);
return dp;
}
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
TextBlock txt = new TextBlock();
Binding b = new Binding();
b.Path = this.Binding.Path;
b.Source = this.Binding.Source;
if (DateFormat != null)
{
DateTimeConverter dtc = new DateTimeConverter();
b.Converter = dtc;
b.ConverterParameter = DateFormat;
}
txt.SetBinding(TextBlock.TextProperty, b);
return txt;
}
protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
{
DatePicker dp = editingElement as DatePicker;
if (dp != null)
{
DateTime? dt = dp.SelectedDate;
if (dt.HasValue)
return dt.Value;
}
return DateTime.Today ;
}
}
This is a converter, in case we want to format the date value
public class DateTimeConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
DateTime date = (DateTime)value;
return date.ToString(parameter.ToString());
}
public object ConvertBack(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
string strValue = value.ToString();
DateTime resultDateTime;
if (DateTime.TryParse(strValue, out resultDateTime))
{
return resultDateTime;
}
return value;
}
}
Once we have these classes and namespace decleration(in my ex. it is mapped to local)
we can just say
<local : DataGridDateColumn DateFormat=”yyyy-MM-dd” Binding=”{Binding HireDate}”/>