For the next week or so, I'll be spending time on building a selector, or whatever I should call it. Basically it's a control that consists of two lists with items, where you can move items from one list to another and back. You've all seem them and a lot of you probably build them as well.
I just got started on the basic features and I already ran into some interesting snags on the way. I first started building the usercontrol with two listboxes, only to get reminded very quickly that they do not support multi select, which is a requirement for our control. After digging some more into the requirements I decided that the datagrid fits our needs better anyway, so I'm using two of those.
One requirement was that the control needs to be able to be used in two orientations, pretty much like the stackpanel. The two lists can be next to each other, with the buttons in between, or they can be above each other, with the buttons in between. I started building them side by side (or in horizontal orientation, if you will), using stackpanels as my container controls. I figured I could change the rotation of my stackpanels to rotate parts of my control. It worked great, except for the captions on the buttons. I would need to rotate these myself.
To do this I embedded a TextBlock element inside the buttons content and named it so I could access it from code. Then I created a RotateTransform object with a 90 degree angle and assigned it to the TextBlocks RenderTransform property, only to find out that my TextBlock would not be in the right place after this. It turns out that the RenderTransformOrigin property defaults to Point 0, 0, which is not right for our rotation. It should rotate around the center of the TextBlock, so it stays in the same place.
I figured that I should calculate a point that indicates the center of the TextBlock and so I set out to do so, only to find out it would completely mess up the location of the TextBlock. I couldn't figure out why, so I fired up Expression Blend to create the rotation in there and see what XAML would come of it. It turned out that the origin should be 0.5, 0.5, which indicates the center of the TextBlock, relative to it's size. Isn't Silverlight genius?
Unfortunately I can't post the full control (yet?), but here is the code for the rotation/orientation of the control:
private void ApplyOrientation()
layoutRootStackPanel.Orientation = Orientation;
if (Orientation == Orientation.Horizontal)
buttonsStackPanel.Orientation = Orientation.Vertical;
unselectItemsTextBlock.RenderTransform = null;
unselectAllItemsTextBlock.RenderTransform = null;
selectItemsTextBlock.RenderTransform = null;
selectAllItemsTextBlock.RenderTransform = null;
buttonsStackPanel.Orientation = Orientation.Horizontal;
RotateTransform rotateTransform = new RotateTransform();
rotateTransform.Angle = 90;
Point centerPoint = new Point(0.5, 0.5);
unselectItemsTextBlock.RenderTransformOrigin = centerPoint;
unselectItemsTextBlock.RenderTransform = rotateTransform;
unselectAllItemsTextBlock.RenderTransformOrigin = centerPoint;
unselectAllItemsTextBlock.RenderTransform = rotateTransform;
selectItemsTextBlock.RenderTransformOrigin = centerPoint;
selectItemsTextBlock.RenderTransform = rotateTransform;
selectAllItemsTextBlock.RenderTransformOrigin = centerPoint;
selectAllItemsTextBlock.RenderTransform = rotateTransform;
I hope this is helpful to you. Please leave me a comment (or a question if you like). I always enjoy them and I try to respond in a timely fashion.