locked
Best way to handle this custom container RRS feed

  • Question

  • So I've created a custom container (just raw XAML) that is basically a StackPanel, with a Grid (with contents), and then a Rectangle painting the reflection of the StackPanel below. It works really well -- but I'm running into some troubles abstracting this out.  My first instict was to use a ControlTemplate. So, I made a template and it worked fairly well using something like:

    <UserControl Template="{StaticResource reflectedBox}">
        <Grid>
        <TextBlock Text="Hello, world!" />
        </Grid>
    </UserControl>

    Unfortunately I had the Width/Height hardcoded in the template... that's not exactly optimal.  So I wanted to set the Width/Height on the <UserControl> and ran into a major snag.  My rectangle effectively makes the container larger. So when I grabbed the Width/Height from the <UserControl> using binding... the display was correct, but got clipped because <UserControl> ended up being half the height it needed to be (to accomodate the Rectangle).

    Is there a better way of approaching this than a ControlTemplate? I could create a custom control and play around with overriding Width and Height, but this seems to go against WPF's philosophy of being able to completely restyle any element you want with Templates.
    Thursday, September 27, 2007 11:01 PM

Answers

  • It sounds to me like the behavior you're trying to provide with this control is simply the reflection of whatever variable content is put inside of it. Am I missing anything?

     

    So you would want that to look something like this in your application:


    Code Block

    <myNS:MyReflectionThingy ... some properties that control the reflection here ...>

    <StackPanel x:Name="MyStackPanel">

    <TextBlock>Example:</TextBlock>

    <TextBox Text="Some random content..." />

    </StackPanel>

    </myNS:MyReflectionThingy>

     

     

    You can certainly achieve this with UserControl using a StackPanel, ContentPresenter and a Rectangle with a VisualBrush bound to ContentPresenter, but there's so much code you need to write anyway to get the reflection effect to happen (measuring, arranging, visual brush scaletransform centerx/y, etc.) that I would make it a Decorator subclass.

     

    You just use the logic you mentioned where, on your Measure pass, you measure whatever is in your Content property and, based on the reflection algorithm you're going to use, maybe double the height of the final size. Then in your Arrange you just put the content at your relative 0,0 coordinate and render the reflection in OnRender starting at the content's Height+1. Do draw the reflection you just use the DrawingContext's DrawRectangle with a VisualBrush that again points to the content. Simple enough rendering logic and much lighter weight.

     

    HTH,
    Drew

    Friday, September 28, 2007 12:07 AM

All replies

  • Just had a recent discussion about this in another thread. You're using UserControl and that's not really the right way to approach a control that is meant to be re-templated. Basically you want to create a ContentControl subclass. Check out that thread and hopefully the details there (read the SDK articles I linked to as well) will help move you in the right direction.

     

    HTH,
    Drew

     

    Thursday, September 27, 2007 11:14 PM
  • Thanks for the response Drew, I actually do remember slightly reading that thread a little while ago. But I guess I'm still confused... one thing you were stressing was that custom controls shouldn't have a particular look & feel -- while that is exactly what I am out to accomplish. Really, the only reason I was using UserControl was so I could get at the Template property (and my naiveness as to which is the most light-weight control that accepts Content & Template). The new container has no new functionality -- only a reflected look that required the addition of a few elements (like a Rectangle).

    Does it make sense to create a custom control that subclasses ContentControl, eats it's own Height property, doubles it and then apply the Template to the custom control tag (in the Main Window, for instance)? I guess that just feels strange to me, as the only reason I'm changing the height is so that the visual representation of the control will not be clipped.
    Thursday, September 27, 2007 11:28 PM
  • It sounds to me like the behavior you're trying to provide with this control is simply the reflection of whatever variable content is put inside of it. Am I missing anything?

     

    So you would want that to look something like this in your application:


    Code Block

    <myNS:MyReflectionThingy ... some properties that control the reflection here ...>

    <StackPanel x:Name="MyStackPanel">

    <TextBlock>Example:</TextBlock>

    <TextBox Text="Some random content..." />

    </StackPanel>

    </myNS:MyReflectionThingy>

     

     

    You can certainly achieve this with UserControl using a StackPanel, ContentPresenter and a Rectangle with a VisualBrush bound to ContentPresenter, but there's so much code you need to write anyway to get the reflection effect to happen (measuring, arranging, visual brush scaletransform centerx/y, etc.) that I would make it a Decorator subclass.

     

    You just use the logic you mentioned where, on your Measure pass, you measure whatever is in your Content property and, based on the reflection algorithm you're going to use, maybe double the height of the final size. Then in your Arrange you just put the content at your relative 0,0 coordinate and render the reflection in OnRender starting at the content's Height+1. Do draw the reflection you just use the DrawingContext's DrawRectangle with a VisualBrush that again points to the content. Simple enough rendering logic and much lighter weight.

     

    HTH,
    Drew

    Friday, September 28, 2007 12:07 AM