Jaime Rodriguez On Windows Store apps, Windows Phone, HTML and XAML
I often get pinged with a "My < insert control or panel here> is clipping ... even though I have set ClipToBounds=false... is this a bug?" ...
It is not a bug; it is just that ( as of today, afaik) the clipping behavior in WPF is not documented completely (yet!)
Here is a sample XAML of what I am talking about:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/interactivedesigner/2006" mc:Ignorable="d" Background="#FFFFFFFF" x:Name="DocumentRoot" Width="640" Height="480" ClipToBounds="False">
<Grid.Resources> <Storyboard x:Key="OnLoaded" RepeatBehavior="5x" > <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="Rectangle"> <SplineDoubleKeyFrame d:KeyEase="Linear;Linear;0.5;0.5;0.5;0.5" KeySpline="0.5,0.5,0.5,0.5" Value="360" KeyTime="00:00:02.0" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="Rectangle2"> <SplineDoubleKeyFrame d:KeyEase="Linear;Linear;0.5;0.5;0.5;0.5" KeySpline="0.5,0.5,0.5,0.5" Value="360" KeyTime="00:00:02.0" /> </DoubleAnimationUsingKeyFrames> </Storyboard> </Grid.Resources>
<Grid.Triggers> <EventTrigger RoutedEvent="FrameworkElement.Loaded"> <BeginStoryboard x:Name="OnLoaded_BeginStoryboard" Storyboard="{DynamicResource OnLoaded}"/> </EventTrigger> </Grid.Triggers> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.20*"/> <ColumnDefinition Width="0.20*"/> <ColumnDefinition Width="0.58125*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="0.12*"/> <RowDefinition Height="0.12*"/> <RowDefinition Height="0.76*"/> </Grid.RowDefinitions> <Button HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0" Width="120" Height="62" Grid.Row="1" Grid.Column="1" ClipToBounds="False" > <Rectangle Stroke="#FF000000" Fill="#FFFFFFFF" Width="90" Height="42" x:Name="Rectangle2" RenderTransformOrigin="0.5,0.5"> <Rectangle.RenderTransform> <TransformGroup> <RotateTransform Angle="0"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> </Button> <Button HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0" Width="120" Height="62" Grid.Row="1" Grid.Column="0" ClipToBounds="False" x:Name="Button" > <Rectangle Stroke="#FF000000" Fill="#FFFFFFFF" Width="90" Height="42" x:Name="Rectangle" RenderTransformOrigin="0.5,0.5"> <Rectangle.RenderTransform> <TransformGroup> <RotateTransform Angle="0"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> </Button></Grid>
**Sorry for lack of graphical creativity, imagine the button is a cool ATM button and the rectangle is an image spinning around telling you "I am doing some work" since the ATM has no cursor ..
If you run it on XAMLPAd or your favorite XAML Editor.. you will see that
1) The rectangle is clipping... why?? Both the Button and the Grid have ClipToBounds = false; it should not be clipping right ?
I use to agree with that until Dmitry, a WPF dev that tends to tolerate all my "dumb questions" around this topic.. shared the skinny... here is a cut & paste from a very old email:
"There are 3 potential sources of clipping behavior for an element:
All of these work independent and result clip is an intersection of all 3 sources."
#1 and #3 are well known ...even I have touched on some (Clipping in particular) …
the missing info is always #2.. LayoutClip?? What is that and where do I get me some?
Actually, what you need is to get rid of it.. You must override in your FrameworkElement GetLayoutClip () and return either a Geometry big enough for what you are doing, or return null (no clip) …
The downside (in my thick headed opinion) is that to get around it, you will have to derive from and override GetLayoutClip ... afaik, there is not a better way :(
So, let's give it a shot: we create a Clipless button .. (UC= UnClipped )
public class UCButton : Button { protected override Geometry GetLayoutClip ( Size ls ) { return null; } }
and update our xaml of course now cut & paste into EID or VS2005 since we have code-behind ...
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/interactivedesigner/2006" mc:Ignorable="d" Background="#FFFFFFFF" x:Name="DocumentRoot" x:Class="UntitledProject1.Scene1" Width="640" Height="480" ClipToBounds="False" xmlns:lcl="clr-namespace:UntitledProject1">
<Grid.Triggers> <EventTrigger RoutedEvent="FrameworkElement.Loaded"> <BeginStoryboard x:Name="OnLoaded_BeginStoryboard" Storyboard="{DynamicResource OnLoaded}"/> </EventTrigger> </Grid.Triggers> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.20*"/> <ColumnDefinition Width="0.20*"/> <ColumnDefinition Width="0.58125*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="0.12*"/> <RowDefinition Height="0.12*"/> <RowDefinition Height="0.76*"/> </Grid.RowDefinitions> <Button HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0" Width="120" Height="62" Grid.Row="1" Grid.Column="1" ClipToBounds="False" > <Rectangle Stroke="#FF000000" Fill="#FFFFFFFF" Width="90" Height="42" x:Name="Rectangle2" RenderTransformOrigin="0.5,0.5"> <Rectangle.RenderTransform> <TransformGroup> <RotateTransform Angle="0"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> </Button> <lcl:UCButton HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0" Width="120" Height="62" Grid.Row="1" Grid.Column="0" ClipToBounds="False" x:Name="Button" > <Rectangle Stroke="#FF000000" Fill="#FFFFFFFF" Width="90" Height="42" x:Name="Rectangle" RenderTransformOrigin="0.5,0.5"> <Rectangle.RenderTransform> <TransformGroup> <RotateTransform Angle="0"/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> </lcl:UCButton></Grid>
Put it together and you will notice the first button no longer clips: success:)
----
I have seen a few folks doing this really cool "part1, part2" .... I have not picked any thing deep enough to do that, but today I am still going to fake it ... cause I need to send a more specific answer.. Sam, stay tuned for part2 (20 min or so) ...
So, I gave you the secret already ... GetLayoutClip () ... that is it ...
MY problem is twice I have sent that answer and they got back to me with "it is still not working" ... mostly because they were trying to do it in a ListBox... Let's walk through it before we see some code:
Apply my lazy factor to the scenario:
This is a listbox with my portfolio ( Stock symbols).. as I MouseOver each ListBox items, it Scales to 150% so I can read the details.. [all you need is to replace the template, for today we will use the same planet datatemplate we used last time, I told you Datatemplates maximized reuse did not I ?
Unfortunately, we are not there yet... Right now, the image is being clipped like this and I can't read the (imaginary) details..
So, who is clipping it? In my experience that varies widely ..
To understand why it varies, you must use Reflector and go look at FrameworkElement:GetLayoutClip ... There are many checks ( MaxWidth/Height) , Margins + RenderSize, etc. that determine what your clip is.. so depending on what you are doing, you might either be clipped by:
Experience taught me to override all at once; don't leave it to luck or the person replacing you will be puzzled a year from now, when they change some thing in the template and this thing starts clipping ...
So, attached is a quick & very dirty example -- don't think of it as a best practice, more of a what to look for list' on how to get around some of the usual gotchas.. Here is what it shows:
OK, I think that is it ... See code attached.... Created using July CTP ... Opens fine in Expression of course.. [but might need to build it once before you can use designer]
jaime, 3 weeks again with no posts at all.. lame..
Sidebar is one of my favorite features in Vista.. It is just so full of business-value opportunities and it is such a low entry point that every one tends to always love it..
It is an extension to the existing "enterprise portal" model that has become so popular and successful over the last few years... but it brings the content to the desktop where I might be able to interact with it in off-line mode or with many less clicks and less overhead than a portal (launch browser, drink a sip, page loads, refresh, etc.) .. with sidebar it is Windows+SpaceBar and I am there..
I should come back to a deeper explanation of what sidebar is.. but in the mean time, start here.
One of my favorite parts of talking about sidebar is that people always have a "must have gadget"... My bro-in-law wants an "ebay gadget" to let him bid and notify him if some one is messing with his (likely to be) new toys; a peer wants an "airline gadget" that tells her when her hubby's plane arrives from business trips... etc..
For me it was weather, with my < 3 year old, I am always looking for when it will be "sunny but not hot" or "at least not raining" so I can plan my outings with him... a few weeks ago, I wrote my weather gadget ... piece of cake, in a couple hours I was running -and most time it took me to find a weather webservice-.. So, I was looking to be a team player and submit my gadget to the "sidebar gallery" but I upgraded to Vista RC1 and the gadget is already there.. my contribution opportunity was killed..
My other "must have gadget" is my "Outlook To-Do Bar"... For those running Office 2007, you know what I am talking about.. This gadget tells me where I need to be with out launching Outlook.. it works in cache mode, etc.. Unfortunately, i am more aprehensive to share that because 1) the UI needs polishing.. 2) It is Outlook code, with PIAs, etc. so harder to package and install and I am not sure I can support it or clean it up enough 3) some one has already contributed a similar gadget to the community.. 4) with my luck, the office team beats me to it again...
So, I need ideas.. Share what your "must have gadget" is.. and I might just write it for you.. Here is my only criteria: I always say that "sidebar was designed to simplify your every day tasks" ... so I want some thing you will use a bit.. some thing that saves you 2 minutes of work a few times a day...
Actually, a second criteria.. for all those service providers/e-commerce enterprises working with me on early adoption projects: I am not writing your gadget... [reaching your customers via sidebar gadgets will make you bundals, least you can do is write your own]
For the rest, I do hope to hear from you ... I committ to writing one during month of september.. [ likely around the 18th or so, cause I have some committments coming]..
Thanks,
Via John Gossman...
At first, I could not believe this there would be a utlility that helped me troubleshoot my WPF bindings... but snoop does :) ...
This also walks you through Visual Tree ( a trick/utlity I use often now a days)
It just happened that I was messing w/ a dynamic layout for overflow stuff ... and snoop also looks handy because I can check exactly the size of my controls as I resize...
The direct link is http://www.blois.us/Snoop/ ... Definitely a MUST Download!!
[back to my overflow problems, using snoop :) ]