Finding Key State using PInvoke in SL5 RC
If we have to find the Key State of CAPS lock, NUM lock etc in silverlight 5 RC, we could do like this using PInvoke
Add the Declaration
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);
And to get the different Key states
bool CapsLock = (((ushort)GetKeyState(0×14)) & 0xffff) != 0;
bool NumLock = (((ushort)GetKeyState(0×90)) & 0xffff) != 0;
bool ScrollLock = (((ushort)GetKeyState(0×91)) & 0xffff) != 0;
Using PInvoke in SL5 to show MessageBox
One of the new features in SL5 is the ability to use PInvoke. This post shows how to use PInvoke to show MesageBox with lot more options.
Start by creating a SL5 OOB application with elevated trust and add the following code
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern MessageBoxResult MessageBox(IntPtr hWnd, String text, String caption, int options);
public enum MessageBoxOptions
{
Ok = 0×000000,
OkCancel = 0×000001,
AbortRetryIgnore = 0×000002,
YesNoCancel = 0×000003,
YesNo = 0×000004,
RetryCancel = 0×000005,
CancelTryContinue = 0×000006,
IconHand = 0×000010,
IconQuestion = 0×000020,
IconExclamation = 0×000030,
IconAsterisk = 0×000040,
UserIcon = 0×000080,
IconWarning = IconExclamation,
IconError = IconHand,
IconInformation = IconAsterisk,
IconStop = IconHand,
DefButton1 = 0×000000,
DefButton2 = 0×000100,
DefButton3 = 0×000200,
DefButton4 = 0×000300,
ApplicationModal = 0×000000,
SystemModal = 0×001000,
TaskModal = 0×002000,
Help = 0×004000, //Help Button
NoFocus = 0×008000,
SetForeground = 0×010000,
DefaultDesktopOnly = 0×020000,
Topmost = 0×040000,
Right = 0×080000,
RTLReading = 0×100000,
}
public enum MessageBoxResult : uint
{
Ok = 1,
Cancel,
Abort,
Retry,
Ignore,
Yes,
No,
Close,
Help,
TryAgain,
Continue,
Timeout = 32000
}
To actually see the messagebox, we could do something like
MessageBoxOptions options = MessageBoxOptions.CancelTryContinue | MessageBoxOptions.DefButton1 | MessageBoxOptions.IconQuestion;
MessageBox(IntPtr.Zero, “This is a messagebox with 3 buttons, one of them being default and a question icon”, “Caption”, (int)options);
Here is the result
Enum’s and MarkupExtension
Here is quick sample to get all the values from an enum using MarkupExtension. This returns a Dictionary
public class EnumValuesExtension : MarkupExtension
{
public string EnumName { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
IXamlTypeResolver xamlResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
Type t = xamlResolver.Resolve(EnumName);
return t.GetFields().Where(field => field.IsLiteral).ToDictionary(x => (int)x.GetValue(null), x => x.Name);
}
}
If we have a enum like below
public enum Days
{
Sat = 1, Sun, Mon, Tue, Wed, Thu, Fri
}
We can use it in xaml like this. ‘local’ is the xmlns declaration pointing to the namespace
<ComboBox Width=”150″ Height=”25″ DisplayMemberPath=”Value”
ItemsSource=”{local:EnumValues EnumName=’local:Days’}”/>
DataGrid random behavior when scrolling
I came across a post in the silverlight forums which shows the random behavior of the DataGrid. This happens obviously only when scrollbars are there and when we scroll. Wraping DataGridRowsPresenter in the Template of the DataGrid in a scrollviewer seems to get around this issue. As scrollviewer has some border margin etc. I styled it to remove all unnecessary stuff.
<ScrollViewer Grid.ColumnSpan=”2″ Grid.Row=”1″ Style=”{StaticResource ScrollViewerStyle1}”>
<sdk:DataGridRowsPresenter x:Name=”RowsPresenter” />
</ScrollViewer>
If you remove the style applied to the DataGrid in the sample you can clearly see the random behavior. You can download the sample here .
DataGrid and “No Records Found” message
Here is one way to display a message when we dont have any data returned
1. Grab the Template of the DataGrid from Blend
2. Modify the Template. All we do is find the RowsPresenter line
<sdk:DataGridRowsPresenter x:Name=”RowsPresenter” Grid.ColumnSpan=”2″ Grid.Row=”1″/>
and move it inside a Grid element, we add in the template in the same place.
The Grid has a TextBlock to show the message and Visibility is controlled by a Converter
Here is the relevant part of the Template
…
<sdk:DataGridColumnHeader x:Name=”TopLeftCornerHeader” Template=”{StaticResource TopLeftHeaderTemplate}” Width=”22″/>
<sdk:DataGridColumnHeadersPresenter x:Name=”ColumnHeadersPresenter” Grid.Column=”1″/>
<sdk:DataGridColumnHeader x:Name=”TopRightCornerHeader” Grid.Column=”2″ Template=”{StaticResource TopRightHeaderTemplate}”/>
<Rectangle x:Name=”ColumnHeadersAndRowsSeparator” Grid.ColumnSpan=”3″ Fill=”#FFC9CACA” Height=”1″ StrokeThickness=”1″ VerticalAlignment=”Bottom” Width=”Auto”/>
<!–<sdk:DataGridRowsPresenter x:Name=”RowsPresenter” Grid.ColumnSpan=”2″ Grid.Row=”1″/>–>
<Grid Grid.ColumnSpan=”2″ Grid.Row=”1″ >
<sdk:DataGridRowsPresenter x:Name=”RowsPresenter”/>
<TextBlock Text=”No Records found”
Visibility=”{Binding ElementName=RowsPresenter, Path=Children.Count, Converter={StaticResource noRecordsConverter}}”
HorizontalAlignment=”Center” VerticalAlignment=”Center”
FontSize=”12″/>
</Grid>
<Rectangle x:Name=”BottomRightCorner” Grid.Column=”2″ Fill=”#FFE9EEF4″ Grid.Row=”2″/>
<Rectangle x:Name=”BottomLeftCorner” Grid.ColumnSpan=”2″ Fill=”#FFE9EEF4″ Grid.Row=”2″/>
<ScrollBar x:Name=”VerticalScrollbar” Grid.Column=”2″ Margin=”0,-1,-1,-1″ Orientation=”Vertical” Grid.Row=”1″ Width=”18″/>
…
And the Converter
public class NoRecordsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString() == “0″ ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
EntityFramework 4, code first and RIA Services
I was looking at EF4 and code first CTP5 and wanted to see how that works with RIA Services. So I took John Papa’s sample from PDC10 and started converting that to use code first.
Here are the steps
1.Becasue we already have a database and want to generate the classes quickly Open the EDMX file right click and add code generation item and select “ADO.NET DbContext Generator” . this will generate the model classes and the context
2.After the classes are generated we will have a BookClubEntities class. we have to change the connectingstring to go directly to database
the modified connection string in Web.Config looks like this
<add name=”BookClubEntities” connectionString=”Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BookClub.mdf;Integrated Security=True;User Instance=True;MultipleActiveResultSets=True” providerName=”System.Data.SqlClient” />
3. we need to override OnModelCreating to add our mapping. All of them are starightforward except for ImageSource column in the Book class. We dont have that in the Database, so we ignore it. Here is the context class after mapping
public partial class BookClubEntities : DbContext
{
public BookClubEntities()
: base(“name=BookClubEntities”)
{
}
public DbSet<BookOfDay> BookOfDays { get; set; }
public DbSet<Book> Books { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Checkout> Checkouts { get; set; }
public DbSet<Member> Members { get; set; }
public DbSet<Request> Requests { get; set; }
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//books
modelBuilder.Entity<Book>().Ignore(x => x.ImageSource);
modelBuilder.Entity<Book>().HasMany(x => x.BookOfDays).WithRequired(x => x.Book).HasForeignKey(x => x.BookID);
modelBuilder.Entity<Book>().HasMany(x => x.Checkouts).WithRequired(x => x.Book).HasForeignKey(x => x.BookID);
modelBuilder.Entity<Book>().HasMany(x => x.Requests).WithRequired(x => x.Book).HasForeignKey(x => x.BookID);
modelBuilder.Entity<Category>().HasMany(x => x.Books).WithRequired(x => x.Category).HasForeignKey(x => x.CategoryID);
modelBuilder.Entity<Member>().HasMany(x => x.Books).WithRequired(x => x.Member).HasForeignKey(x => x.MemberID);
modelBuilder.Entity<Member>().HasMany(x => x.Checkouts).WithRequired(x => x.Member).HasForeignKey(x => x.MemberID);
modelBuilder.Entity<Member>().HasMany(x => x.Requests).WithRequired(x => x.Member).HasForeignKey(x => x.MemberID);
modelBuilder.Entity<Checkout>().HasMany(x => x.Requests).WithRequired(x => x.Checkout).HasForeignKey(x => x.CheckoutID);
}
}
3. We have to map the classes to Tables, whereever the tablename differs from the class name we add “Table” attribute on the class for mapping and add “Key” attributes on the primary columns
4. We add Association Attribute on all the properties that we want to include in our results.
5. Add the DbContextExtensions file. it contains useful extension methods. (I got the code from the EF forums posted by a user and refined by person from MSFT)
6. Last but not least change the code in the actual service to inherit from DomainService and modify the queries to go against the context we created and not ObjectContext
If all the mappings are right, we should have the application working again without the edmx file.
You can download the files changed or added here. This zip file has only the relevant files, not the whole application.
Prism 4 – Silverlight and Custom Commands
Silverlight 4 includes commanding support for ButtonBase classes, but for anything else we would need to write a little bit of code.
There is a nice section here on how to extend this to other situations. Here is a quick sample on how to create command support for MouseLeftButtonDown on an UIElement. You can download the code from here.
Here is how we can use the Command behavior we create for invoking a command on the mouseleftbutton up event
<UserControl x:Class=”SLPrismCustomCommands.MainPage”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation“
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml“
xmlns:d=”http://schemas.microsoft.com/expression/blend/2008“
xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006“
mc:Ignorable=”d”
xmlns:local=”clr-namespace:SLPrismCustomCommands”
d:DesignHeight=”300″ d:DesignWidth=”400″>
<Grid x:Name=”LayoutRoot” Background=”White”>
<Ellipse Fill=”Green” Width=”20″ Height=”20″
local:Click.CommandParameter=”{Binding RelativeSource={RelativeSource Self}}”
local:Click.Command=”{Binding MyCommand}”/>
</Grid>
</UserControl>
The following would create a behavior
public class MouseLeftButtonDownBehavior : CommandBehaviorBase<UIElement>
{
public MouseLeftButtonDownBehavior(UIElement obj)
: base(obj)
{
if (obj == null) throw new System.ArgumentNullException(“object cannot be null”);
obj.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseButton);
}
private void OnMouseButton(object sender, System.Windows.RoutedEventArgs e)
{
ExecuteCommand();
}
}
Here is the class for the Attached properties
public static class Click
{
private static readonly DependencyProperty ClickCommandBehaviorProperty = DependencyProperty.RegisterAttached(
“ClickCommandBehavior”,
typeof(MouseLeftButtonDownBehavior),
typeof(Click),
null);
/// <summary>
/// Command to execute on click event.
/// </summary>
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
“Command”,
typeof(ICommand),
typeof(Click),
new PropertyMetadata(OnSetCommandCallback));
/// <summary>
/// Command parameter to supply on command execution.
/// </summary>
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached(
“CommandParameter”,
typeof(object),
typeof(Click),
new PropertyMetadata(OnSetCommandParameterCallback));
/// <summary>
/// Sets the <see cref=”ICommand”/> to execute on the click event.
/// </summary>
/// <param name=”buttonBase”>UIElement dependency object to attach command</param>
/// <param name=”command”>Command to attach</param>
public static void SetCommand(UIElement element, ICommand command)
{
if (element == null) throw new System.ArgumentNullException(“element”);
element.SetValue(CommandProperty, command);
}
/// <summary>
/// Retrieves the <see cref=”ICommand”/> attached to the <see cref=”ButtonBase”/>.
/// </summary>
/// <param name=”buttonBase”>ButtonBase containing the Command dependency property</param>
/// <returns>The value of the command attached</returns>
public static ICommand GetCommand(UIElement element)
{
if (element == null) throw new System.ArgumentNullException(“element”);
return element.GetValue(CommandProperty) as ICommand;
}
/// <summary>
/// Sets the value for the CommandParameter attached property on the provided <see cref=”ButtonBase”/>.
/// </summary>
/// <param name=”buttonBase”>ButtonBase to attach CommandParameter</param>
/// <param name=”parameter”>Parameter value to attach</param>
public static void SetCommandParameter(UIElement element, object parameter)
{
if (element == null) throw new System.ArgumentNullException(“element”);
element.SetValue(CommandParameterProperty, parameter);
}
/// <summary>
/// Gets the value in CommandParameter attached property on the provided <see cref=”ButtonBase”/>
/// </summary>
/// <param name=”buttonBase”>ButtonBase that has the CommandParameter</param>
/// <returns>The value of the property</returns>
public static object GetCommandParameter(UIElement element)
{
if (element == null) throw new System.ArgumentNullException(“element”);
return element.GetValue(CommandParameterProperty);
}
private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
UIElement element = dependencyObject as UIElement;
if (element != null)
{
MouseLeftButtonDownBehavior behavior = GetOrCreateBehavior(element);
behavior.Command = e.NewValue as ICommand;
}
}
private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
UIElement element = dependencyObject as UIElement;
if (element != null)
{
MouseLeftButtonDownBehavior behavior = GetOrCreateBehavior(element);
behavior.CommandParameter = e.NewValue;
}
}
private static MouseLeftButtonDownBehavior GetOrCreateBehavior(UIElement element)
{
MouseLeftButtonDownBehavior behavior = element.GetValue(ClickCommandBehaviorProperty) as MouseLeftButtonDownBehavior;
if (behavior == null)
{
behavior = new MouseLeftButtonDownBehavior(element);
element.SetValue(ClickCommandBehaviorProperty, behavior);
}
return behavior;
}
}
and here is the code for the CommandBehaviorBase
public class CommandBehaviorBase<T> where T : UIElement
{
private ICommand command;
private object commandParameter;
private readonly WeakReference targetObject;
private readonly EventHandler commandCanExecuteChangedHandler;
/// <summary>
/// Constructor specifying the target object.
/// </summary>
/// <param name=”targetObject”>The target object the behavior is attached to.</param>
public CommandBehaviorBase(T targetObject)
{
this.targetObject = new WeakReference(targetObject);
// In Silverlight, unlike WPF, this is strictly not necessary since the Command properties
// in Silverlight do not expect their CanExecuteChanged handlers to be weakly held,
// but holding on to them in this manner should do no harm.
this.commandCanExecuteChangedHandler = new EventHandler(this.CommandCanExecuteChanged);
}
/// <summary>
/// Corresponding command to be execute and monitored for <see cref=”ICommand.CanExecuteChanged”/>
/// </summary>
public ICommand Command
{
get { return command; }
set
{
if (this.command != null)
{
this.command.CanExecuteChanged -= this.commandCanExecuteChangedHandler;
}
this.command = value;
if (this.command != null)
{
this.command.CanExecuteChanged += this.commandCanExecuteChangedHandler;
UpdateEnabledState();
}
}
}
/// <summary>
/// The parameter to supply the command during execution
/// </summary>
public object CommandParameter
{
get { return this.commandParameter; }
set
{
if (this.commandParameter != value)
{
this.commandParameter = value;
this.UpdateEnabledState();
}
}
}
/// <summary>
/// Object to which this behavior is attached.
/// </summary>
protected T TargetObject
{
get
{
return targetObject.Target as T;
}
}
/// <summary>
/// Updates the target object’s IsEnabled property based on the commands ability to execute.
/// </summary>
protected virtual void UpdateEnabledState()
{
if (TargetObject == null)
{
this.Command = null;
this.CommandParameter = null;
}
else if (this.Command != null)
{
TargetObject.IsHitTestVisible = this.Command.CanExecute(this.CommandParameter);
}
}
private void CommandCanExecuteChanged(object sender, EventArgs e)
{
this.UpdateEnabledState();
}
/// <summary>
/// Executes the command, if it’s set, providing the <see cref=”CommandParameter”/>
/// </summary>
protected virtual void ExecuteCommand()
{
if (this.Command != null)
{
this.Command.Execute(this.CommandParameter);
}
}
}
RIA services and combobox lookups with Async CTP
If we are editing data in a datagrid and have a few combobox columns, it will be difficult to know when the data is ready for all the comboboxes. The Async CTP that was released will help.
I got the extension method Kyle McClellan wrote in this post to consume LoadOperations as Tasks.
I had the following setup to display data from Products table in Northwind database in a Datagrid with Suppliers and categories as Comboboxes for editing.
<sdk:DataGrid AutoGenerateColumns=”False” Name=”dataGrid1″ ItemsSource=”{Binding Products}”>
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header=”Name” Binding=”{Binding ProductName}”/>
<sdk:DataGridTemplateColumn Header=”Supplier”>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text=”{Binding Supplier.CompanyName}”/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource=”{Binding Source={StaticResource root}, Path=DataContext.Suppliers}”
SelectedValuePath=”SupplierID”
DisplayMemberPath=”CompanyName”
SelectedValue=”{Binding SupplierID, Mode=TwoWay}” />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header=”Category”>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text=”{Binding Category.CategoryName}”/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource=”{Binding Source={StaticResource root}, Path=DataContext.Categories}”
SelectedValuePath=”CategoryID”
DisplayMemberPath=”CategoryName”
SelectedValue=”{Binding CategoryID, Mode=TwoWay}” />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTextColumn Header=”QuantityPerUnit” Binding=”{Binding QuantityPerUnit}”/>
<sdk:DataGridTextColumn Header=”UnitPrice” Binding=”{Binding UnitPrice}”/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
The Domain service methods for getting categories and suppliers are going to return data after 5 and 3 sec.<
public IQueryable<Category> GetCategories()
{
Thread.Sleep(5000);
return this.ObjectContext.Categories;
}
public IQueryable<Supplier> GetSuppliers()
{
Thread.Sleep(3000);
return this.ObjectContext.Suppliers;
}
The Page is bound to instance of a ViewModel. If we use the GetData method to load the data, we can see that data is not loaded yet for the Categories and Suppliers columns. If we use GetDataAsync method to load the data, we are going to see the datagrid populated when all the related data is there.
public class MainViewModel : INotifyPropertyChanged
{
public IEnumerable<Supplier> Suppliers { get; set; }
public IEnumerable<Category> Categories { get; set; }
public IEnumerable<Product> Products { get; set; }
NorthwindDomainContext ctx = new NorthwindDomainContext();
public MainViewModel()
{
//GetData();
GetDataAsync();
}
async void GetDataAsync()
{
Task<LoadOperation<Product>> productTask = ctx.Load(ctx.GetProductsQuery()).AsTask();
Task<LoadOperation<Category>> categoryTask = ctx.Load(ctx.GetCategoriesQuery()).AsTask();
Task<LoadOperation<Supplier>> supplierTask = ctx.Load(ctx.GetSuppliersQuery()).AsTask();
await TaskEx.WhenAll(productTask, categoryTask, supplierTask);
Suppliers = supplierTask.Result.Entities;
Products = productTask.Result.Entities;
Categories = categoryTask.Result.Entities;
NotifyPropertyChanged("Suppliers");
NotifyPropertyChanged("Categories");
NotifyPropertyChanged("Products");
}
void GetData()
{
ctx.Load<Product>(ctx.GetProductsQuery(), (lo) => { Products = lo.Entities; NotifyPropertyChanged("Products"); }, false);
ctx.Load<Category>(ctx.GetCategoriesQuery(), (lo) => { Categories = lo.Entities; NotifyPropertyChanged("Categories"); }, false);
ctx.Load<Supplier>(ctx.GetSuppliersQuery(), (lo) => { Suppliers = lo.Entities; NotifyPropertyChanged("Suppliers"); }, false);
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
you can download the code from here
