Thursday, November 6, 2008

WPF Windows in WinForms project

Sometimes we need to add WPF windows to the Windows Forms project in Visual Studio. But, from all the WPF items,  Visual Studio allows to create only UserControl.
So I can think of two possible solutions here: a) we can create a custom item template for Visual Studio, or b) we can think something out of the UserControl.
If we do not need to create WPF windows on a constart rate, the second approach can be used.
So, we create new WPF UserControl and than replace UserControl with Window in both xaml and cs  files - in this way we get a WPF window in a WinForms project :)

Wednesday, July 23, 2008

WPF experience - different stages

It seems to me that the experience could be split into several different stages when you work with WPF.

1. You are amazed: You type xml tags and something shows up! Cool! And those animations - ultra cool!!!

2. Trying to develop...a lot...gain experience....and still happy :)

3. You begin to understand how things work, you learn what the ItemsControl is from inside, you understand how to implement the application in a "correct" way and know how are you expected to use the framework in a right way. Now you are a bit disappointed because of the limitations - the WPF does not handle everything...

4. You implement something that is....incompatible with WPF. WPF is not as great as before, or you even start hating it.

5. You understand all benefits and limitations of WPF and start using its best parts and omit bad parts. You finally recall what the development is about (some think that it is about the usage of a technology and not about making the product). Life becomes better :)

6. You are really happy with what you are doing; you make the product and do not worry about the technology limitations.

7. You are ready to move to the next technology to be able to mix them in future.

Seems that I am currently on stage 6 and WPF is really great when you need GUI :) 

Monday, July 21, 2008

GET, POST and fetching HTTP with HttpWebRequest

Once upon a time there was a HttpWebRequest.  He tried to GET some HTML from YouTube to feed his web browser. HttpWebRequest had default settings and only the URL was unique, so YouTube said - Go request yourself, Bad Request 400!

I have done some basic investigation and found out that usually it is important to provide the Referrer field. So when I added that field  (request.Referrer = url;) - the request worked fine for the moment...

But later I decided that I would like to POST some data to the site...I set the request method to POST (request.Method = "POST";), set content type to "multipart/form-data", specified multipart boundary and updated ContentLength (request.ContentLength = xxx;). I opened the request stream (request.GetRequestStream();) and started writing POST form data to it (and calling stream.Flush() from time to time).

After I sent the request I needed the response, so I called request.GetResponse() and read out all data from the stream it returned. (BTW - do not forget to close streams :) )

I noticed that the data is not correct, or at least some part of it is missing (the one at the beginning), so I proceeded with the investigation.

I found out that the header Expect is set to 100-continue, and the web site was against that approach. So I needed to turn it off - I used such setting : request.ServicePoint.Expect100Continue = false;

Usually I also set the UserAgent field and Accept field.

Thursday, June 5, 2008

Two names of a single element

It turned out that one element in WPF can have two (or even more!) names. For example you create UserControl, and add it to the Window. Like that:

<Window>
    <MyControl Name="Control1"/>
</Window>

And inside the control (I mean the XAML file that defines the control) you make a Binding to the control itself, so you need to specify the ElementName. Like that:

<MyControl Name="Root">
    <TextBlock Text="{Binding Path=Property1, ElementName=Root}"/>
</MyControl>

So, as you can see, MyControl element has two different names at the same time: Control1 and Root. But how is it possible? The answer will be like following: Different name scopes (I mean NameScope class that implements INameScope interface).

So how did we get two different name scopes for a single element? The secret is that when the UserControl is defined in XAML, and it's XAML definition is loaded, new name scope is created for the control automatically, and all names, that are set inside the control's XAML file or inside its visual tree, goes to its own name scope. And the name, defined in a window definition (like Control1 ), is registered in a windows name scope.

So that is all the magic you need :)

Monday, May 26, 2008

How do I provide custom collection view for collection in WPF?

Some time ago, while "surfing" the WindowsBase.dll with Reflector, I have found one interesting interface: ICollectionViewFactory.
I made some digging, and found out that there are folks that are interested what is this interface doing (along with some other interesting interfaces...)
MSDN says nothing about this interface, but it turned out that it could be quite useful in fact.
Here is how it is declared:

/// An interface that enables implementing collections to create a view to their data. Normally, user code does not call methods on this interface.
public interface ICollectionViewFactory
{
/// Creates a new view on the collection that implements this interface. Typically, user code does not call this method.
/// The newly created view.
ICollectionView CreateView();
}

It turned out that when you try to create a default collection view for the collection(or when you provide your collection as an items source for the ItemsControl), databinding engine checks whether your collection implements ICollectionViewFactory interface, and if it does - your CreateView() method is called, so in case you want to implement some specific logic, like optimized grouping, or specific filtering - you just implement your own collection view and return it in CreateView() method.

Tuesday, May 20, 2008

My level in XAML :)

Several hours ago The Moth (seems to be Daniel in real life) have posted an article on the levels of XAML understanding.

The proposed leveling is as following:
Level 100 – truly understand all of the above.
Level 200 – confidently read XAML (e.g. as spat out by VS2008 or Blend).
Level 300 – be able to type XAML yourself with an aim to create a structure of a bland GUI (setting basic properties and hooking events etc).
Level 400 – create styles, templates, animations and set gradient colours by hand.

I think, that everyone, who created at least one custom control for WPF (well, I mean something that could be sold), have already achieved the XAML competency level 400 :) At least most of my coworkers did and so did I. I even think that there should be one more level - 500, like God-Like...I do not think that I have achieved such level but it seems that I am somewhere between 400 and 500.

Level 500 means that you definitely know how to implement something in code that could be used correctly in XAML :) Also such level includes knowing how every tag and attribute in XAML works (like the problem with focus scopes, when you should know from the beginning that moving element to the new focus scope will change the behavior of standard WPF controls).

But any way - now we have some kind of competency levels for XAML writers :) Great!

Sunday, May 18, 2008

Post2Blog - Windows client for Blogger, or blogging outside the IE

Recently I have decided that I do not like to make posts in my blog using it’s web-interface, so I have decided to find some windows client for Blogger engine. I have done some search and found a post about the Post2Blog software, so now I am writing this post using that program, and also I am thinking on how can I make money on something like that :-) BTW - funny notice - at the time when a guy wrote his post about this staff, it costed about $40, and now it is free. If I were him, I would be a bit upset now :-)


Post2Blog is really cool application - it supports a variety of blogging engines (Blogger and WorldPress for example), it supports automatic images upload (I do not think that I will use that feature, but still - it is there for free :-)), and finally - it is FREE.


There is one thing that seems to be missing - Blog2Post is all about posting to the blog and not managing the blog, so the access to the recent posts is a bit confusive...but still - great staff, wonder could it be abandoned and became free...

Friday, April 25, 2008

Great resource for SEO-beginners

Hm... recently I have googled into one veeeery usefull (for SEOs) post
I found that blog while I was searching for the ways to trackback my own posts from other blog-engines so that I could see the list of the links to my posts...

Thursday, April 24, 2008

XAML+LoadComponent VS pure code - where are my name scopes???

Recently my coworker faced one interesting problem. He was looking through the sample for the Josh's article on 3D in WPF, and said that he had noticed one strange thing - whenever you try to replace the loading of the Viewport3D from XAML with in-code creation, you get an exception in RegisterName methods, saying that there is no name scope for the provided element.
So, what is the difference between loading XAML and creating element from code? I made a short research using the greatest tool in a .NET world, Reflector, and it turned out that in case when XamlReader (or, to be more specific, BamlRecordReader) meets some element, that does not support INameScope interface, it creates the namescope itself, and attaches it to the element (NameScope.SetNameScope(dependencyObject, new NameScope());).
Finally, to resolve the issue with an exception, we have manually created the NameScope and attached it to the viewport.
Also, XamlReader calls BeginInit and EndInit methods whenewer the loaded element supports ISupportInitialize interface. So you should remember to use that too when you create visual element in code.

Thursday, April 10, 2008

WPF tips: Get your own logical parent

Have you ever wondered how does the Popup knows its inheritance context, its logical parent and the route for the routed events after you set PlacementTarget property? Or how does the ContextMenu knows where to fire the commands?
Today I have incidentally found the answer.
Whenever you have the FrameworkElement, that does not have any kind of parent set directly( neither visual, nor logical ), you can choose your parent yourself :)
To do so, you should override GetUIParentCore() method and return whatever logical parent you want – one-way link will be created, so you will know who is your parent, and your parent could unaware of your existence :)
BTW Popup returns its PlacementTarget property value in this method.

This mechanism could be used to implement custom inheritance context in some cases, so it is really important to remember of its existence.

Saturday, April 5, 2008

Public Folder Watcher

Yesterday I have created one more blog - the one for the Public Folder Watcher (blog is here).

Public Folder Watcher is a small addon for Microsoft Outlook, written by me.

I decided to implement it as soon as we installed Microsoft Exchange Server on our server at ArtfulBits.

We needed to share some data among all of the developers(and so do now), so at the time, Public Folders were the most suitable for that. But there were no notifications about the new items in Public Folders, so such approach was useless and so I decided to implement this addon :)

Now I can not even imagine how our company would live without this small addon - it monitors both Public Folders and emails and displays the list of the unread emails and posts. Almost all of my coworkers (at least 40 of them) and all of the managers use Public Folder Watcher to be always aware of the new emails or posts.

I hope others will find this addon usefull too and regard me for my work with 15$ :) That means that the Public Folder Watcher can be downloaded here, it's trial key can be got here, and it can be bought here .

Friday, April 4, 2008

Weird solutions: Ho can I force WPF control to rerender itself.

Today I found out some strange solution for forcing control to invalidate itself.

It turned out that by default control invalidates itself only in case it's render size has been changed, his visual parent has been changed, or some of it's dependency properties with AffectsRender option set is changed. (also there are some other weird cases when control suddenly decides to rerender it's appearance)

So I decided that maybe I can use FrameworkElement's ability to react to the AffectsRender option - I implemented the attached dependency property, and tried setting it to some rendom values on an object I needed to invalidate...and it worked :)

Here is some sample class, that could be used to implement such workaround:


public class RenderingHelper : DependencyObject
{
private static int s_last = 0;

public static int GetForceRerender( DependencyObject obj )
{
return (int)obj.GetValue( ForceRerenderProperty );
}
public static void SetForceRerender( DependencyObject obj, int value )
{
obj.SetValue( ForceRerenderProperty, value );
}

public static readonly DependencyProperty ForceRerenderProperty = DependencyProperty.RegisterAttached( "ForceRerender", typeof( int ), typeof( RenderingHelper ),
new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsRender ) );


public static void InvalidateRender( Visual target )
{
SetForceRerender( target, s_last++ );
}
}



You should keep in mind that invalidation of a visual calls it's OnRender method and recreates only part of the elements visual graph. All Visual's children are left the same, so if you need to invalidate the appearance of the entire visual subtree, you should add FrameworkPropertyMetadataOptions.Inherits to the property options.

Friday, March 14, 2008

Why InvalidateZOrder is not public???

The worst case of what you can implement on WPF is custom control. In this case you have to use most of the extensebility of the framework, and it turns out that it is just, well, non-extensible...

Today it turned out that there is no way to change the z-order of the element if it's parent is not a Panel, and there is no way I can use Panel as a parent because it tries to steal my logical children :(

It also turned out that there is no way to change z-order without making this:

foreach( Visual child in children )
{
RemoveVisualChild( child );
AddVisualChild( child );
}

And that could be avoided if a method of a Visual, called InvalidateZOrder, would not be internal :(

Tuesday, March 11, 2008

Canceling keyboard focus change in WPF

Hah! Today I found out that the keyboard focus transition in WPF  is cancellable :)
It turned out that you should "handle" PreviewLostKeyboardFocus routed event (just set it's Handled to True) and magic happens - focus does not go anywhere.
Still, there are some cases when this event is not raised, for example, when user just Alt-Tabs to another application, but that does not matter in most cases :)

Sunday, March 9, 2008

MuVo and its Firmware

As I already said in a preious post, I want to say some words about how I updated firmware on my MuVo v200 (it's not really my - I bought it for my girlfriend 2 years ago, but now it is replaced with her new mobile phone, so she does not use the player anymore).

First of all, what made me to update the firmware: sometimes the device could decide that it does not want to play anything...and it really did not play anything :) It even could not find any tracks on a flashdrive, and after that even I could not find those tracks on a flashdrive :)

So that is why I decided to make an update... I went to the Creative site, found the downloads page, selected my player and than I was asked of the OS I am using. I use Vista, so I selected in in a list and there was no firmware updates found. Than I clicked "Back" and selected Windows XP for the downloads filter...and there it was - I could clearly see the list to the latest firmware for my player.

I downloaded the update and tried to install it on my PC, but installer said that my OS is not supported (BTW, the same as with my Creative SoundBlaster Live 5.1). So I decided to attach the player to my server (that is running Windows 2003 server). In this way I solved the Vista-problem.

Using the terminal connection, I was able to run the update. It started to search for the player(I have already plugged it into the USB), and in a second or two I have been warned that the player will be reset. I clicked the confirmation button, hoping that it would start updating the firmware, but the only chage, I got, was the following message: "Fail to locate recovery driver needed for firmware upgrading".

So now I had to solve one more problem - I did not know anything about the "recovery driver" and there was no instruction for the firmware update. After some investigations with Goolge and Far (I use it for all kind of operations with files :) ) I found out two things:
1) Firmware update software package already contained the required driver, but it did not install it
2) My player supports the Recovery Mode, and I can put it into this mode manually - after that it will start searching for the driver, mentioned in 1).

So, I unplugged player, pressed Play button and, while holding it pressed, attached the player to PC again. After 10 seconds of holding the play button (I found out about that here), new device was found - some unknown recovery mode device. I tried to install the driver for it, abandoned the automatic install and selected the driver, that was stored in a temporary folder where it was extracted by the firmware updater (in my case that was C:\Documents and Settings\Administrator\WINDOWS\temp\CRF000\, but the updater should be running while you are installing the driver :) a bit tricky :) ). After I installed the driver for that stranger recovery device, I was pretty sure that now the firmware update should work correctly...and I was right - after I unlpugged and than plugged in the played again, I started the firmware update, it found my player, notified of it's reset, put it into recovery mode, updated the firmware and switched the player into the normal mode again :)

I think, next time, I will just go and replace the player with a new one, that is made by someone unrelated with the Creative company, instead of updating the firmware :):) If someone has the same problem with "Fail to locate recovery driver needed for firmware upgrading" and my post is too long and confusing - feel free to write a comment and I will give some step-by-step walkthough :)

Intro

"Hi" to everyone, who reads this :)

Today I decided to create my own blog (I do not count my LiveJournal account as a blog, the same with my account at Lviv .NET community - first is for russian-speaking crowd only, and the second one is intended to be used only for .NET related stuff, or at least development-related)

So at this blog I will write some of my thoughts about my life, and about my beloved work :)
BTW, as for the work - I'm some kind of mix of a developer, project manager, multiple projects manager and just the guy who does all researches :) I use C#, .NET 3.5, WinForms and WPF in my work, so I will post some of my findings here sometime...

Next, I will write about how I have updated firmware on my Creative MuVo v200 :)