Thank you, Murkaeus. You got me going in the right direction.
In the end, I created a custom control that inherited from Page, defining a ContentProperty for it. This apparently overrides the ContentProperty of the base class. And this works for any control type, too. Here is my code:
[ContentProperty("Children")]
class CustomPage : System.Windows.Controls.Page
{
ObservableCollection<UIElement> children = new ObservableCollection<UIElement>();
public ObservableCollection<UIElement> Children { get { return children; } set { children = value; } }
}
Then I defined the template for my control in the Themes/Generic.xaml file with an ItemsControl using my custom ContentProperty as a source:
<Style TargetType="local:CustomPage">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ItemsControl ItemsSource="{Binding Children,
RelativeSource={RelativeSource TemplatedParent}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I hope this helps anyone else who is looking for a solution to the same problem. And thank you again, Murkaeus, for your help!
EDIT: I should warn everyone that if you use this method, all your data bindings are lost for some reason, I discovered this with further experimentation. I ended up giving up and just specifying a panel as the child of my custom page object.