Archive for Silverlight

An Early Look at Silverlight Model-View-ViewModel Toolkit 1

Introduction

This post is just an early look of upcoming Silverlight Model-View-ViewModel Toolkit. I know that this is very early state but I’m writing about this here because I would like to get the feedbacks from the community so that I can prioritize the plans based on what the community want. If you are a fan of WPF MVVM Toolkit then you will probably like it.

Silverlight MVVM Toolkit

Download : SilverlightModelViewApplication.zip (15 KB)

Features

The toolkit includes:

  • A Visual Studio 2008 Project Template
  • Silverlight Command Implementation
  • ViewModelBase that implements INotifyPropertyChanged interface

What is Silverlight MVVM Toolkit?

Silverlight MVVM Toolkit is a Visual Studio project template that has some useful pre-written implementations for Silverlight Command and INotifyPropertyChanged interface. The main intention of creating this toolkit is to help developers to develop the MVVM pattern-based Silverlight application quickly.

I’ve been using this template since a few weeks ago and I found it quite useful because whenever I need to create some samples for my blog or the POC projects for my Office, I always need to create a ViewModal class that implements INotifyPropertyChanged interface and need to add the Prism V2 assembly as a reference in my sample for using DelegateCommand. When I look at WPF MVVM toolkit, I really like it because it saves a lot of my times for copying and pasting the old code from my old sample to new sample. After using WPF MVVM toolkit, I was thinking why not create a project template for Silverlight as well. and now, I did it.

The project template is already attached in this post so you can download and test it in your machine. The msi file for that template is not ready yet but I will show you very simple steps (just two steps only) to make it visible in Project Template Dialog of Visual Studio 2008.

How to install Silverlight Model-View-ViewModel Toolkit

Please download the zip file (Don’t extract it) and close all Visual Studio 2008 instances before following the steps below ~

Step #1: Copy and paste SilverlightModelViewApplication.zip under this path below

%ProgramFiles%\Microsoft Visual Studio 9.0\
Common7\IDE\ProjectTemplates\CSharp\Silverlight\1033

    VS Project Template

Step #2. Open Visual Studio 2008 Command Prompt and type “deven /setup”

commandline

Yes. That’s all for installing new project template for Visual Studio.

Once you have finished registering new project template, you open the Visual Studio 2008 and check “New Project” dialog.  Then, you will get new project template “Silverlight Model View Application” under Silverlight project type as shown in picture below.

Silverlight MVVM Template in VS

Choose that template to create a Silverlight MVVM appliction. Note that linking with ASP.NET project, enabling the RIA service and generating unit-test project are not availble in this template but I will add all of this later.

The structure of Silverlight MVVM project is as below.

Silverlight MVVM Folder Structure

Commends

Let’s talk about classes under Commands.  The Command implementation that I’m using in this toolkit is from CompositeWPF version 2. I know that I can probably roll my own implementation but I’ve been using Prism for long time and DelegateCommand is working perfectly fine so I dont think that I need to waste my time to do the duplicated things. Please feel free to let me know if you found something that is not supported by DelegateCommand.

Here is the examples for using DelegateCommand.

XAML


xmlns:cmd="clr-namespace:SilverlightModelViewApplication4.Commands"

Here is how you can use Command Binding and CommandParameter in Silverlight.  ( The earlier implementation of Prism v2 is cmd.Command.Click but Prism team re-named this to Click.Command at drop 9.  You can read this post if you like to know why they did the changes)


<Button
cmd:Click.Command="{Binding SearchCommand}"
cmd:Click.CommandParameter="This is a CommandParameter"
/>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 2503px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><Button</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 2503px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">cmd:Click.Command="{Binding SearchCommand}"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 2503px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">cmd:Click.CommandParameter="This is a CommandParameter"</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 2503px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">/></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 2503px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

C#


public DelegateCommand<string> SearchCommand { get; set; }

//Construtor
public MainPageViewModel()
{

SearchCommand = new DelegateCommand<string>((arg) =>
{
MessageBox.Show(arg);
});

}

INotifyPropertyChanged implementation

Some of you might know that I wrote about how to implement INotifyPropertyChanged interface with Expression Tree so you don’t need to use any magic string in property setter.  If you haven’t read it yet, please go and read this post to get some idea. I implemented the same implementation in ViewModelBase class of this toolkit so you can probably use this feature as below in ViewModel class.


//Example: How to use RaisePropertyChanged without having any magic string.

private string name = string.Empty;

public string Name
{
get { return name; }
set {
name = value;
this.RaisePropertyChanged(p => p.Name);
}
}

Upcoming Features ~

  • A Project Template Waziard for linking with ASP.NET, enabling RIA Services and generating a Text project that has the references o Silverlight Unit Test Framework and Silverlight Moq
  • A C# and VB.NET project template that supports all editions (inlcuding express edition) of Visual Studio 2008
  • Creating a msi installer by using Windows Installer XML (WiX) toolset

Questions?

I have a few questions for you guys.

  1. What kind of functionalities do you guys like to see in this toolkit? For example: Extensions/Attached properties, Utilities and etc
  2. Do you think that I should create an installer (msi) for that? OR is it okay to have zip file and register it by youself with two simple steps? I’m asking you this because in order to create a msi, I will probably need to spend some times for learning Windows Installer XML (WiX) toolset. So, if you guys are okay with two simple steps, I can work on other things first.

Feel free to drop a comment if you have any comment or suggestion for this toolkit. If you already have similar things in your mind, please let me know. We can work together to contribute our community. You can also reach me with this email mchlsync AT gmail DOT com.

I will be hosting this project in codeplex.com once it’s ready.

Silverlight Attached Properties: Binding.UpdateSourceTrigger.PropertyChanged

Note: It is one of my answers from Silverlight Forum.

Problems

UpdateSourceTrigger is not supported in Silverlight until version 3.o.

Workaround

You will need to set the focus on other controls and re-focus to the control that you are using. For example: You are typing in TextBoxA. You want to have UpdateSourceTrigger support for that textbox. So, what you have to do is that you need to change the focus on another control (e.g. TextboxB) and re-set the focus on TextboxA while typing.

Yes. you can do it very easily from code-behind. But ( genius? ) people from pattern world don’t like the idea of using code-behind file (so, creating a code-behind file for each and every xaml in Visual Stuid is a waste? What about changing the default pattern (MVC) to MVVM in Visual Stuido Template? ) Anyway, let me get back to the topic. So, we can probably create an attached property to workaround the UpdateSourceTrigger in Silverlight.

Note: This code is just giving you some idea how you can workaround the issue. You will need to do the modification based on your need.

Let’s name our attached property aS “UpdateSourceTriggerHelper”. We will add some codes for registering the property and getter/setter as below. I will tell you more about OnUpdateSourceTriggerChanged


public class UpdateSourceTriggerHelper
{
public static readonly DependencyProperty UpdateSourceTriggerProperty =
DependencyProperty.RegisterAttached("UpdateSourceTrigger", typeof(bool), typeof(UpdateSourceTriggerHelper),
new PropertyMetadata(OnUpdateSourceTriggerChanged));

public static bool GetUpdateSourceTrigger(DependencyObject d)
{
return (bool)d.GetValue(UpdateSourceTriggerProperty);
}

public static void SetUpdateSourceTrigger(DependencyObject d, bool value)
{
d.SetValue(UpdateSourceTriggerProperty, value);
}

In OnUpdateSourceTriggerChanged method, we are going to add the logic for focusing other controls and re-setting the focus back to the original control. So, we need to walk throught the Visual Tree to get the object of other control. Please take a look at findFocusableControl();


private static void OnUpdateSourceTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = d as TextBox;
if ((bool)e.OldValue)
{
textBox.TextChanged -= (s, arg) => {

};
}
if ((bool)e.NewValue)
{
textBox.TextChanged += (s, arg) => {
var c = findFocusableControl(textBox);
if (c != null)
{
c.Focus();
}
textBox.Focus();
};
}
}

Let’s take a look at what we did in findFocusableControl(). Based on the control that you are typing, you can get the parent of control by using VisualTreeHelper. But if you want to use this code in production, you will have to modify the code. (For example: if you can’t find any parent then you will need to find the child element. and you need to check whether that control that you get from Visual Tree Helper is focusable or not. yes. there are a lot of things to do it.)


private static Control findFocusableControl(Control control)
{
var ctl = VisualTreeHelper.GetParent(control);
if ((ctl as Control) != null)
{
return ctl as Control;
}
else
{
int childrenCount = VisualTreeHelper.GetChildrenCount(ctl);
for (int i = 0; i < childrenCount; i++)
{
var c = VisualTreeHelper.GetChild(ctl, i) as Control;
if ((c != null) &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; (c != control))
{
return c;
}
}
}
return null;
}
}

Here is how we can use our attached property to provide PropertyChanged event.

Usage (Example)


<UserControl x:Class="UpdateSourceTriggerExtDemo.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UpdateSourceTriggerExtDemo"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<TextBox x:Name="nameTextbox" Height="25" Width="100" Margin="5" Text="{Binding Name, Mode=TwoWay}"
local:UpdateSourceTriggerHelper.UpdateSourceTrigger="True" />
<TextBox x:Name="addressTextbox" Height="25" Width="100" Margin="5" Text="{Binding Address, Mode=TwoWay}"
local:UpdateSourceTriggerHelper.UpdateSourceTrigger="False" />
<TextBox x:Name="phoneTextbox" Height="25" Width="100" Margin="5" Text="{Binding Phone, Mode=TwoWay}"
/>
<Button Height="25" Width="100" Margin="5" Content="Save" />
</StackPanel>
</Grid>
</UserControl>

Hope it helps. Feel free to let me know if you have any better solution.. I’m always open to any suggestion from you guys. Thanks..

Happy Silverlighting!!!

Be careful when you are naming the Silverlight Class Library!!

Do you know why? because there are some limitations that you can’t use when you are naming Silverlight Class Library. It happened to us. We named one of our Silverlight Class Libraries with “.Resources” postfix. Then, we got a lot of trouble. I’m not sure whether you guys are aware of this “by-design” issue or not. We got a lot of headaches when we are implementating the localization for WPF and Silverlight project. We have spent around 1 or 2 days just to solve this problem.

Here is the steps to reproduce the issue.

  1. Create Silverlight Application (e.g. SilverlightApplication4 ) with web project attached.  (both Silverlight 2 or Silverlight 3)
  2. Add Silverlight Class Library and named it “ABCDE.Resources”  <Note: This is very important.>
  3. Add the following method in Class1.
    
    public static string Foo(){
    return "Foo";
    }
    
  4. Add ”ABCDE.Resources” as a reference in SilverlightApplication4.
  5. Go to Page.xaml.cs
  6. Add the following line in constructor.
    
    Console.WriteLine(ABCDE.Resources.Class1.Foo());
    

Error:

Could not load file or assembly ‘ABCDE.Resources, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. The system cannot find the file specified.

I got that error and also, I found that “ABCDE.Resources” assembly is not getting generated in Silverlight. So, I reported this issue in WPF/Silverlight Insider List. What I heard from Microsoft is that this is by-design issue. Silverlight’s application activation logic treats this with special meaning – it recognizes such an assembly as a satellite resource assembly. Then, I tried to reproduce the issue  just like the way that we used in our project without using any code but just resx file.

Here is new steps to reproduce the issue.

  1. Create Silverlight Application (e.g. SilverlightApplication4 ) with web project attached.  (both Silverlight 2 or Silverlight 3)
  2. Add Silverlight Class Library and named it “ABCDE.Resources”  <Note: This is very important.>
  3. Add new resx file (Let’s call it “Strings.resx”)
  4. Change “Access Modifier :” to Public
  5. Add new string to that resx file “Strings.resx”
    e.g: (Name: YourMessageStringInResx, Value=YourMessageStringValueInResx)
  6. Go to Code-behind of that resx file “Strings.Designer.cs” and change private constructor to public. (why? yes. this is another issue. )
  7. Go to Page.xaml.cs
  8. Add the following line in constructor.
    
    Console.WriteLine(Strings.YourMessageStringInResx);
    

Then, run the application. I’m sure that you will get the same error. I’m still waiting the response from Microsoft for that issue and I will update this post as soon as I get one. As of now, the only solution for this issue is that don’t name “.Resources” for your class library and use other name like ABCDE.Languages or ABCDE.Rex or etc.

Hope it helps.

Silverlight/WPF: Implementing PropertyChanged with Expression Tree

Source Code: RaisePropertyChangedExample.zip [94.4 KB]

Credits: Thanks to Paul Strong and Soe Moe for sharing this code with me.

Introduction

This article will show you how to implement INotifyPropertyChanged interface with Expression Tree. I’m sure that the most of WPF/Silverlight developer are already familier with implementing INotifyPropertyChanged interface because this is the most important thing that you have to do when you want to notify the changes of property value to the Clients. But here is with Expression Tree. The most of us used to pass the property name as a string to the PropertyChanged event. Why Expression Tree here? Passing the property name as a string doesn’t just work? No, it works but passing a string is not safe. what if you forget to update the string if you are re-naming the Property. The compiler won’t remind you that you have failed to update the string. Of course, you can verify the name like Josh mentioned in his article. But still, you will know only when you run the program. This is where Expression Tree come in. You can use VS Reflector to rename when you are changing the property name. If not, the compiler will remind you to change.

Let’s take a look at the first sample. The class “PageViewModel” implements INotifyPropertyChanged event just as the way that we always do. There is no super cool things inside.


public class PageViewModel : INotifyPropertyChanged
{
private string name = string.Empty;

public string Name
{
get
{
return name;
}
set
{
name = value;
this.RaisePropertyChanged("Name");
}
}

public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

But if you are developing the project, there won’t be just one class so implementing INotifyPropertyChanged become tireding process. So, I would suggest to create a base class ( I will call it “ObservableBase ” in this article) so that all classes that need to be implemented INotifyPropertyChanged interface can inherit from that class.


public abstract class ObservableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

public void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

After creating a base class as above, we can change our PageViewModel to inhert from base class so we can completely remove all codes that we used for implementing INotifyPropertyChanged event.


public class PageViewModel : ObservableBase
{
private string name = string.Empty;
public string Name
{
get
{
return name;
}
set
{
name = value;
this.RaisePropertyChanged("Name");
}
}
}

But we are still passing the string to RaisePropertyChanged method. How should we change it to Expression Tree? Yes, we will need to change our base class a little bit. The first thing that come into my mind is that to add one more event that can accept the expression. Let’s check out the sample below.


public void RaisePropertyChanged<TValue>(Expression<Func<TValue>> propertySelector)
{
if (PropertyChanged != null)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
}
}
}

After changing this, we can call that method from setter as below.


private string name = string.Empty;
public string Name
{
get {
return name;
}
set {
name = value;
this.RaisePropertyChanged<string>( () => this.Name);
}
}

But why <string>? Is there any way to avoid this? My friend, Soe Moe, come up with the solution that uses C# extension method to avoid having the generic type defined in setter. It’s pretty cool. Please check-out the extension method below.


public static class ObservableBaseEx
{
public static void RaisePropertyChanged<T, TProperty>(this T observableBase, Expression<Func<T, TProperty>> expression) where T : ObservableBase
{
observableBase.RaisePropertyChanged(observableBase.GetPropertyName(expression));
}

public static string GetPropertyName<T, TProperty>(this T owner, Expression<Func<T, TProperty>> expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
{
var unaryExpression = expression.Body as UnaryExpression;
if (unaryExpression != null)
{
memberExpression = unaryExpression.Operand as MemberExpression;
if (memberExpression == null)
throw new NotImplementedException();
}
else
throw new NotImplementedException();
}

var propertyName = memberExpression.Member.Name;
return propertyName;
}
}

Finally, we can call the RaisePropertyChanged event without specifing any generic type. Cool, huh?


private string name = string.Empty;
public string Name
{
get {
return name;
}
set {
name = value;
this.RaisePropertyChanged( p => p.Name);
}
}

Yes. I’m open to any better solution that you have. Please feel free to let me know if you have better idea. You can also download my sample (both WPF and Silverlight included in zip) and play a bit as well. :)

Thanks for reading!

References

Silverlight 3: Array Helper

Here is the collection of Array-related functions that are missing in Silverlight. I will upload the sample file with Unit Test later. The Silverlight Unit Test Framework which is released in December is not upgraded with Silverlight 3 so I will wait for new version.

Please feel free to give any suggestion, feedback or report any bug that you are testing. I really appreciate for that. As of now, I really don’t like the idea of using try-catch in my code. I will change it to something else later.

Silverlight – Array.ConvertAll

This method is the equivalent function of System.Array.ConvertAll. It allows you to convert an array of one type to an array of another.


public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] array, Converter<TInput, TOutput> converter) {
if (array == null)
throw new ArgumentException();

return (from item in array select converter(item)).ToArray();
}

Example:


float[] af = {27.8F, 32.62F,99.3F,147.273F,7.5F,1412.2F };

int[] ai = ArrayExtension.ConvertAll(af,new Converter<float, int>((f) => (int)f));

foreach (var i in ai) {
MessageBox.Show(i.ToString());
}

Silverlight – Array.Exist(T)

This method is the equivalent function of System.Array.Exist(T). It allows you to determine whether the specified array contains elements that match the conditions defined by the specified predicate.


public static bool Exists<T>(this T[] array,
Predicate<T> match) {
if (array == null)
throw new ArgumentException();

return array.Any(item => match(item));
}

Example:


string[] dinosaurs = { "Compsognathus",
"Amargasaurus",   "Oviraptor",      "Velociraptor",
"Deinonychus",    "Dilophosaurus",  "Gallimimus",
"Triceratops" };

MessageBox.Show(string.Format(
"\nArray.Exists(dinosaurs, EndsWithSaurus): {0}",
ArrayExtension.Exists(dinosaurs, (s) => {
if ((s.Length > 5) &amp;&amp; (s.Substring(s.Length - 6).ToLower() == "saurus")) {
return true;
}
else {
return false;
}
})
)
);

Silverlight – Array.Find(T)

This method is the equivalent function of System.Array.Find(T). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire Array.


public static T Find<T>(this T[]  array,
Predicate<T> match) {
if (array == null)
throw new ArgumentException();

return (from item in array where match(item) select item).FirstOrDefault();
}

Example:


Point[] points = { new Point(100, 200),
new Point(150, 250), new Point(250, 375),
new Point(275, 395), new Point(295, 450) };

Point first = ArrayExtension.Find(points, (p) => {
if (p.X * p.Y > 100000) {
return true;
}
else {
return false;
}
});

Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);

Silverlight – Array.FindAll(T)

This method is the equivalent function of System.Array.FindAll(T). It allows you to retrieve all the elements that match the conditions defined by the specified predicate.


public static T[] FindAll<T>(T[] array,
Predicate<T> match) {
if (array == null)
throw new ArgumentException();

return (from item in array where match(item) select item).ToArray();
}

Example:


string[] dinosaurs = { "Compsognathus",
"Amargasaurus",   "Oviraptor",      "Velociraptor",
"Deinonychus",    "Dilophosaurus",  "Gallimimus",
"Triceratops" };

string[] subArray =
ArrayExtension.FindAll(dinosaurs, (s) => {
if ((s.Length > 5) &amp;&amp;
(s.Substring(s.Length - 6).ToLower() == "saurus")) {
return true;
}
else {
return false;
}
});

foreach (string dinosaur in subArray) {
MessageBox.Show(dinosaur);
}

Silverlight – Array.FindIndex(T)

  • FindIndex(T)(T[], Predicate(T))
  • FindIndex(T)(T[], Int32, Predicate(T))
  • FindIndex(T)(T[], Int32, Int32, Predicate(T))

Silverlight – Array.FindIndex(T)(T[], Predicate(T))

This method is the equivalent function of System.Array.FindIndex(T)(T[], Predicate(T)). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the entire Array.


public static int FindIndex<T>(T[] array, Predicate<T> match) {
if (array == null)
throw new ArgumentException();

try {
var v = array
.Select((item, index) => new { item = item, position = index })
.Where(x => match(x.item)).FirstOrDefault();
return v.position;
}
catch {
return -1;
}
}

Silverlight – Array.FindIndex(T)(T[], Int32, Predicate(T))

This method is the equivalent function of System.Array.FindIndex(T)(T[], Int32, Predicate(T)). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the range of elements in the Array that extends from the specified index to the last element.


public static int FindIndex<T>(T[] array, int startIndex, Predicate<T> match) {

if (array == null)
throw new ArgumentException();

if (startIndex >= array.Count()) {
throw new ArgumentOutOfRangeException();
}

try {
var v = array
.Select((item, index) => new { item = item, position = index })
.Where((x, index) => match(x.item) &amp;&amp; (index >= startIndex)).FirstOrDefault();

return v.position;
}
catch {
return -1;
}
}

Silverlight – FindIndex(T)(T[], Int32, Int32, Predicate(T))

This method is the equivalent function of System.Array.FindIndex(T)(T[], Int32, Int32, Predicate(T)). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the range of elements in the Array that starts at the specified index and contains the specified number of elements.


public static int FindIndex<T>(T[] array, int startIndex, int count, Predicate<T> match) {
if (array == null)
throw new ArgumentException();

if (startIndex >= array.Count()) {
throw new ArgumentOutOfRangeException();
}

if (startIndex < 0 || count < 0) {
throw new ArgumentOutOfRangeException();
}

try {
var v = array
.Where((obj, index) => (index >= startIndex) &amp;&amp; (index <= count))
.Select((item, index) => new { item = item, position = index })
.Where((x, index) => match(x.item) &amp;&amp; (index >= startIndex) &amp;&amp; (index <= count)).FirstOrDefault();

return v.position;
}
catch {
return -1;
}
}

Example:


public void TestFindIndex() {
string[] dinosaurs = { "Compsognathus",
"Amargasaurus",   "Oviraptor",      "Velociraptor",
"Deinonychus",    "Dilophosaurus",  "Gallimimus",
"Triceratops" };

//Result: Array.FindIndex(dinosaurs, EndsWithSaurus): 1
MessageBox.Show(string.Format(
"\nArray.FindLastIndex(dinosaurs, EndsWithSaurus): {0}",
ArrayExtension.FindIndex(dinosaurs, EndsWithSaurus))
);

//Result: Array.FindIndex(dinosaurs, 4, EndsWithSaurus): 5
MessageBox.Show(string.Format(
"\nArray.FindLastIndex(dinosaurs, 4, EndsWithSaurus): {0}",
ArrayExtension.FindIndex(dinosaurs, 4, EndsWithSaurus))
);

//Result: Array.FindIndex(dinosaurs, 4, 3, EndsWithSaurus): -1
MessageBox.Show(string.Format(
"\nArray.FindLastIndex(dinosaurs, 4, 3, EndsWithSaurus): {0}",
ArrayExtension.FindIndex(dinosaurs, 4, 3, EndsWithSaurus))
);
}
private static bool EndsWithSaurus(String s) {
if ((s.Length > 5) &amp;&amp;
(s.Substring(s.Length - 6).ToLower() == "saurus")) {
return true;
}
else {
return false;
}
}

Silverlight – Array.FindLast(T)

This method is the equivalent function of System.Array.FindLast(T). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the last occurrence within the entire Array.


public static T FindLast<T>(T[] array,Predicate<T> match) {
return array
.Last(item => match(item));
}

Example:


string[] dinosaurs = { "Compsognathus",
"Amargasaurus",   "Oviraptor",      "Velociraptor",
"Deinonychus",    "Dilophosaurus",  "Gallimimus",
"Triceratops" };

MessageBox.Show(string.Format(
"\nArray.FindLast(dinosaurs, EndsWithSaurus): {0}",
ArrayExtension.FindLast(dinosaurs, (s) => {
if ((s.Length > 5) &amp;&amp;
(s.Substring(s.Length - 6).ToLower() == "saurus")) {
return true;
}
else {
return false;
}
}))
);

Silverlight – Array.FindLastIndex

  • FindLastIndex(T)(T[], Predicate(T))
  • FindLastIndex(T)(T[], Int32, Predicate(T))
  • FindLastIndex(T)(T[], Int32, Int32, Predicate(T))

Silverlight – FindLastIndex(T)(T[], Predicate(T))

This method is the equivalent function of System.Array.FindLastIndex(T)(T[], Predicate(T)). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the first occurrence within the entire Array.


public static int FindLastIndex<T>(T[] array, Predicate<T> match) {
if (array == null)
throw new ArgumentException();
try {
var v = array
.Select((item, index) => new { item = item, position = index })
.Last(x => match(x.item));

return v.position;
}
catch (Exception e) {
return -1;
}
}

Silverlight – FindLastIndex(T)(T[], Int32, Predicate(T))

This method is the equivalent function of System.Array.FindLastIndex(T)(T[], Int32, Predicate(T)). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the last occurrence within the range of elements in the Array that extends from the first element to the specified index.


public static int FindLastIndex<T>(T[] array, int startIndex,  Predicate<T> match) {

if (array == null)
throw new ArgumentException();

if (startIndex >= array.Count()) {
throw new ArgumentOutOfRangeException();
}
try {
var v = array
.Where((obj, index) => index >= startIndex)
.Select((item, index) => new { item = item, position = index })
.Last(x => match(x.item));
return v.position;
}
catch (Exception e) {
return -1;
}
}

Silverlight – FindLastIndex(T)(T[], Int32, Int32, Predicate(T))

This method is the equivalent function of System.Array.FindLastIndex(T)(T[], Int32, Int32, Predicate(T)). It allows you to search for an element that matches the conditions defined by the specified predicate, and returns the zero-based index of the last occurrence within the range of elements in the Array that contains the specified number of elements and ends at the specified index.


public static int FindLastIndex<T>(T[] array,int startIndex,int count,Predicate<T> match){

if (array == null)
throw new ArgumentException();

if (startIndex >= array.Count()) {
throw new ArgumentOutOfRangeException();
}

if (startIndex < 0 || count < 0) {
throw new ArgumentOutOfRangeException();
}

try {
var v = array
.Where((obj, index) => (index >= startIndex) &amp;&amp; (index <= count))
.Select((item, index) => new { item = item, position = index })
.Last(x => match(x.item));
return v.position;
}
catch (Exception e) {
return -1;
}
}

Example:


public void TestFindLastIndex() {
string[] dinosaurs = { "Compsognathus",
"Amargasaurus",   "Oviraptor",      "Velociraptor",
"Deinonychus",    "Dilophosaurus",  "Gallimimus",
"Triceratops" };

//Result: Array.FindLastIndex(dinosaurs, EndsWithSaurus): 5
MessageBox.Show( string.Format(
"\nArray.FindLastIndex(dinosaurs, EndsWithSaurus): {0}",
ArrayExtension.FindLastIndex(dinosaurs, EndsWithSaurus))
);

//Result: Array.FindLastIndex(dinosaurs, 4, EndsWithSaurus): 1
MessageBox.Show(string.Format(
"\nArray.FindLastIndex(dinosaurs, 4, EndsWithSaurus): {0}",
ArrayExtension.FindLastIndex(dinosaurs, 4, EndsWithSaurus))
);

//Result: Array.FindLastIndex(dinosaurs, 4, 3, EndsWithSaurus): -1
MessageBox.Show(string.Format(
"\nArray.FindLastIndex(dinosaurs, 4, 3, EndsWithSaurus): {0}",
ArrayExtension.FindLastIndex(dinosaurs, 4, 3, EndsWithSaurus))
);
}
private static bool EndsWithSaurus(String s) {
if ((s.Length > 5) &amp;&amp;
(s.Substring(s.Length - 6).ToLower() == "saurus")) {
return true;
}
else {
return false;
}
}

Silverlight – Array.TrueForAll(T)

This method is the equivalent function of System.Array.TrueForAll(T). It allows you to determine whether every element in the array matches the conditions defined by the specified predicate.


public static bool TrueForAll<T>(T[] array, Predicate<T> match) {
if (array == null)
throw new ArgumentException();

return array.Any( item => match(item));
}

Example:


private void TrueForAllTest() {
string[] dinosaurs = { "Compsognathus",
"Amargasaurus",   "Oviraptor",      "Velociraptor",
"Deinonychus",    "Dilophosaurus",  "Gallimimus",
"Triceratops" };

MessageBox.Show(string.Format(
"\nArray.TrueForAll(dinosaurs, EndsWithSaurus): {0}",
ArrayExtension.TrueForAll(dinosaurs, EndsWithSaurus))
);
}
private static bool EndsWithSaurus(String s) {
if ((s.Length > 5) &amp;&amp;
(s.Substring(s.Length - 6).ToLower() == "saurus")) {
return true;
}
else {
return false;
}
}

ArgumentOutOfRangeException

I’m using ArugmentOutOfRangeException in some of my code that I posted above. So, you may need to copy the following code when you are testing my codes.


public class ArgumentOutOfRangeException : SystemException {
public ArgumentOutOfRangeException(){}
public ArgumentOutOfRangeException(string message) { }
public ArgumentOutOfRangeException(string message, Exception innerException) { }
public ArgumentOutOfRangeException(string message, string paramName) { }
//public override string Message { get; }
}

Yes. That’s all. I found those functions very useful when you are doing Silverlight-port for the existing codes. As I mentioned before, please feel free to give any suggestion/feedback.  Thanks.

References ~

Download Silverlight 3 (Beta1) – Download

Download Links for Silverlight 3 (beta1)