Sunday, June 12, 2011

Set focus to Silverlight application and to a scrollviewer content

First, when the webbrowser is displaying the Silverlight app, the HTML element of the Silverlight plugin(object tag) might not have the focus.

This is independent of the Silverlight focus.

I've written a simple test Silverlight application which starts a DispatcherTimer and outputs in the debug output the currently focused element:

The MainPage xaml:
Background="White">

The code behind:
public partial class MainPage : UserControl
{
DispatcherTimer t = new DispatcherTimer()
{
Interval = new TimeSpan(0, 0, 1)
};
public MainPage()
{
InitializeComponent();
t.Tick += new EventHandler(t_Tick);
t.Start();
}

void t_Tick(object sender, EventArgs e)
{
object elem = FocusManager.GetFocusedElement();
if (elem == null)
{
Debug.WriteLine("Reported focused element is null");
}
else
{
Debug.WriteLine(elem);
}
}
}

The "Reported focused element is null" is written to debug output.

Using this method we can see which element has focus in the application and try to fix it.

What I did next is to set the focus in the Loaded event:

public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
t.Tick += new EventHandler(t_Tick);
t.Start();
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
this.Focus();
}

This makes it to report that MyControl has the focus.

Note that if we would remove MyControl it will says that no control has focus, even if we focus to the main page control.
That's because there is no control in the MainPage which can have the focus. All focusable elements are the ones deriving from Control class.

Also, if we keep MyControl but remove the this.Focus() call from Loaded, it will still report that no control has focus.

Now, having MyControl and this.Focus() call set, we still cant process any key press on the MyControl.
That's because the focus is not set to the HTML Element of the Silverlight plugin (the object tag).
This also shows that focus in Silverlight is different then the real focus in HTML page, between the HTML elements of the page.
What's interesting is that we can process the key press in the main page control.
So even if the FocusManager reports null, the key press events can be process on the main page control.

In order to set focus on the Silverlight app, we have two options.
#1 We can make it from the HTML:


Make sure the object tag has id set:


#2. Make it from app code:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.Plugin.Focus();
}

Now we can process the keys in the MyControl control.
We don't need to call this.Focus() anymore.

What I wanted next is to put the MyControl in a ScrollViewer

Background="White">

Without IsTabStop the focus goes to the ScrollViewer.
But with it, the reported focused element is null.
I changed the way focus is set by posting the call in the thread's message stack:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Dispatcher.BeginInvoke(() =>
{
HtmlPage.Plugin.Focus();
});
}

This made it to work.
Without using BeingInvoke, it didn't work.


Thursday, November 05, 2009

Removing path point tangent in Expression Blend

I had situations went I wanted to remove the corner roundness of path points.
For instance, you have a path created from a rectangle with corner radius and you want to make the bottom left and right corners have no roundness.

For this, select the point and with ALT down just click the point and the tangent should be removed.

Wednesday, November 26, 2008

DataGrid custom sorting

As you know DataGrid can sort your items by default when column headers are clicked.
You can however implement your own custom sorting.

When you bind your DataGrid instance to a source object, beside other things it will also look to see if your object implements ICollectionView interface. If it does, it will use it when you click the column headers, if it doesn't it will create and use an internal ICollectionView implementation.

The definition for ICollectionView in MSDN is
"Enables collections to have the functionalities of current record management, custom sorting, filtering, and grouping."
From my investigation, the DataGrid control will only use the custom sorting from your ICollectionView implementation.

To implement custom sorting you need to implement:
1. CanSort property:
bool CanSort { get; }

2. SortDescriptions property:
SortDescriptionCollection SortDescriptions { get; }

The DataGrid control will first call the CanSort property of your ICollectionView implementation. If it returns true it will then call SortDescriptions to get the SortDescriptionCollection collection to use when sorting is triggered.

The
SortDescriptionCollection is a collection of SortDescription objects. When you click on a column header to sort the items by the column, what DataGrid does is to add a new SortDescription object to the SortDescriptionCollection. If you click again on another column the previous SortDescription object is removed from the SortDescriptionCollection and a new SortDescription object is added to the SortDescriptionCollection collection.
Practically, the
SortDescriptionCollection is the representation of the sorting glyph icons you see drawn on the column headers.

A SortDescription object is an object with 2 properties: a property name and sorting direction.
The property name is the name of the property to sort the list by.

That being said, let's write a simple implementation of a simple data source (a list of integers) for a DataGrid control which also implements ICollectionView.

public class MyDataSource : List, ICollectionView
{
SortDescriptionCollection sortDescColl = new MySortDescriptionCollection();
bool CanSort
{
get
{
return true; // this indicates the DataGrid control that we have a valid SortDescriptionCollection returned by SortDescriptions
}
}

SortDescriptionCollection SortDescriptions
{
get
{
return sortDescColl;
}
}
}

We create a new class MySortDescriptionCollection derived from SortDescriptionCollection just to override the InserItem to catch when new columns should get sorted.

public class MySortDescriptionCollection : SortDescriptionCollection
{
    protected override void InsertItem(int index, SortDescription item)
{
// new column was clicked to be sorted
// here we should operate the changes to the
MyDataSource collection
}
}

MySortDescriptionCollection will need to notify MyDataSource somehow about the sorting.
You can use do this with a public event for example. Have the MySortDescriptionCollection to expose a public event for example.

Tuesday, September 16, 2008

Extract all files from MSI

msiexec /a msifilepath /qb TARGETDIR=folderpath

Example: msiexec /a c:\testfile.msi /qb TARGETDIR="c:\my test\"

Wednesday, July 30, 2008

'AG_E_RUNTIME_METHOD : Begin' error when starting a storyboard

Before starting animation, always make sure that animation objects and objects participating in the animation are added to the application's main object tree.
var myControl = plugIn.content.createFromXaml(a.loader.GetResponseText(part), true);
myControl.findName('myStoryBoard').Begin();
parentCanvas.children.add(myControl);

On Silverlight 1, this code will result an (infamous) error: AG_E_RUNTIME_METHOD : Begin

The solution is simple, add the created object first to main object tree and then start the animation:
var myControl = plugIn.content.createFromXaml(a.loader.GetResponseText(part), true);
parentCanvas.children.add(myControl);
myControl.findName('myStoryBoard').Begin();

This is obvious when looking to simple code like this, but in a bigger application it might not look so.
It's 'interesting' that in Silverlight 2.0 this error does not appear.

Thursday, March 13, 2008

vtable and __declspec(novtable) (aka ATL_NO_VTABLE)

__declspec(novtable) is a storage-class attribute and Microsoft specific applied to classes declaration.
It's purpose is to tell the compiler to not add the default vtable initialization\deinitialisation code in the class ctor\destructor.
When the compiler sees a class with virtual methods, it automatically adds vtable init\deinit code in the class ctor\destructor methods. Remember that the vtable is pointer to an array of pointers of the class virtual methods. I guess the initializatio is needed at the ctor time because at the time when your ctor method code is entered, the inner workings of the C++ object need to be initialized. Note that although the vtable is available on thee ctor code, its useless to use it, i.e. calling any virtual method. This is because the vtable of any derived class is not yet initialized.

So, using __declspec(novtable) we will not have the vtable initialized\deinitialized in the ctor\destructor methods.
This means that we cannot use the vtable in any way. More specifically, it means we cannot call any of the object's virtual method.

This has interesting effects. The obvious use is for interfaces, classes with pure virtual functions.

class __declspec(novtable) IFoo
{
public:
virtual ~IFoo()
{
}

virtual void foo() = 0;
};

class FooImpl : public IFoo
{
public:
virtual void foo();
};

IFoo* p = new FooImpl();
p->foo();

So the ctor\dctor of IFoo doesn't have any vtable initialization code as FooImpl has.
When we call foo() on the object the compiler sees that we use a pointer to an object and the method is virtual. Hence, it will use the vtable to get to the method. Vtable is a hidden pointer data in a class. It is always the first data when looking at the raw object in memory.
The FooImpl ctor initialized the vtable so the call is legit and always succeeds.
Remember that although the we call the Foo method of a pointer to IFoo, the vtable hidden data points to the FooImpl.
The vtable pointer is always the same in the raw object in all class derivations.

Another legit code is the following one:

class __declspec(novtable) A {
virtual void func1() { cout<<1; }
virtual void func2() { cout<<2; }
virtual void func3() { cout<<3; }
};

class A1 : public A {
// no func1, func2, or func3
};

It is OK to write:
A* p = new A1();
p->func1();
p->func2();
p->func3();

because A1 ctor initialize the object vtable.

And its NOT OK to write:
A* p = new A();
A->func1(); // undefined behaviour
p->func2(); // undefined behaviour
p->func3(); // undefined behaviour

It is OK to write:
A p;
p.func1();
p.func2();
p.func3();

because calling methods not using a pointer does not make use of vtable.

When using the novtable specifier, always think if the vtable is needed.
For example, you cannot use novtable for a class calling virtual methods in ctor\destructor. This is because the novtable told the compiler to omit the code which initialize the vtable before entering the ctor code.

This is very well described in the paper:
http://msdn.microsoft.com/msdnmag/issues/0300/c/