views:

47

answers:

1

I have an control that is subclassed from ItemsControl, called WorkSheet.

public sealed class WorkSheet : ItemsControl {

It's elements are forced to be WorkTiles.

    /// <inheritdoc />
    protected override bool IsItemItsOwnContainerOverride(object item) {
        return (item is WorkTile);
    }

    /// <inheritdoc />
    protected override DependencyObject GetContainerForItemOverride() {
        return new WorkTile();
    }

So far - so good. I want the WorkSheet to use a Canvas for presenting the WorkItems, position being determined by overriing ArrangeOverride, which is called and positions properly determined. The exact psosition is being determined in overrides. I am pretty lost in the styling, though. I simply can not get the items to appear. In The Generic.xaml, I have defined the styles. They work, but not as they should:

<Style TargetType="{x:Type local:WorkSheet}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Border>
                    <ItemsPresenter />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <ContentPresenter />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Here,pretty much, in the presentation tree, the ItemsPresenter is the lowest element. The subelements iof ItemsPresenter never appear. I also tried putting a Canvas into the ControlTemplate with IsItemsHost="true" - again, no items. Anyone any idea what I am doing wrong here?

Again, as explanation - I put a breakpoint into a button handler on the form and use the Visualizer to see the visual tree. The hierarchy I get is:

WorkSheet -> Border -> ItemsPresenter ... and nothing below.

Obviously this means the ControlTemplate is used, but the ItemsPanel is never invoked.

+1  A: 

Place a TargetType in your ControlTemplate as well:

<ControlTemplate TargetType="{x:Type local:WorkSheet}">

Does not work ;)

Update 2:

I replicated your things in a side project and you have two problems:

First problem is the ItemTemplate setter in your Style which will trigger a StackOverflow exception (how ironic ;)). Remove the ContentPresenter, remove the whole template or use keys.

Second problem is the GetContainerForItemOverride method. Removing this method will give me stuff on screen!

Here is my code:

public sealed class WorkSheet : ItemsControl
{
    /// <inheritdoc />
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is WorkTile);
    }

}

And the xaml of Window with the Style:

<Window x:Class="WpfApplication8.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfApplication8="clr-namespace:WpfApplication8"
    Title="Window1" Height="300" Width="300">

    <Window.Resources>
        <Style TargetType="{x:Type WpfApplication8:WorkSheet}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate >
                        <Border>
                            <ItemsPresenter />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>

    <Grid>
        <WpfApplication8:WorkSheet x:Name="sheet" />
    </Grid>
</Window>
Arcturus
Did not work - same behavior. Any other ideas? More important: Any reference for why this TargetType is needed as the ControlTemplate is IMHO already bound to one specific type through the style. Just trying to understand.
TomTom
Updated my answer!
Arcturus
Yes, got it working. Still do not understand what actually went wrong ;) I tried - adding my own code again now (to the class).
TomTom
Mostly got it working - thanks. Only problem now - the moment I override ArrangeOverride, all client items disappear. This is also the case if the ArrangeOverride only reads: protected override Size ArrangeOverride(Size finalSize) { return finalSize; }. WITHOUT the ArrangeOverrride override - the items appear. Any idea for that?
TomTom
When you override the ArrangeOverride, you should not return the finalSize just like that. The method expects you to calculate the size, and when the size is Infinite, you wont see a thing. Better to return new Size(Width, Height) or just call the base.ArrangeOverride(finalSize), and let them calculate it for you! Hope this clears it up a bit ;)
Arcturus
Got it - finally. Thanks. Seems ArrangeOverride base call is needed. Never had Infinite, but still was invisible unless ArrangeOverride made a call to it's "base" implementation.
TomTom