I am trying to create a very flexible custom control. The flexibility that I'm trying to achieve to be able to bind UserControl to the ExpanderContent Dependency property, code behind snippet:
public partial class ChartBar : UserControl { public UIElement ExpanderContent { get { return (UIElement)GetValue(ExpanderContentProperty); } set { SetValue(ExpanderContentProperty, value); } } // Using a DependencyProperty as the backing store for ExpanderContent. This enables animation, styling, binding, etc... public static readonly DependencyProperty ExpanderContentProperty = DependencyProperty.Register("ExpanderContent", typeof(UIElement), typeof(ChartBar), new PropertyMetadata(null, OnExpanderContentChanged)); private static void OnExpanderContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //throw new NotImplementedException(); } . . . I have tried using a ContentPresenter in the XAML but it doesn't work. I obviously can fill with buttons and it works but this defeats the dynamic content via binding.
<Expander x:Name="expander" Header="" VerticalAlignment="Top" d:LayoutOverrides="Width" Style="{DynamicResource ExpanderStyle1}"> <ContentPresenter Content="{Binding ExpanderContent, ElementName=TestControlWithContent}" /> <!--<WrapPanel HorizontalAlignment="Center" > <Button Content="A" Style="{DynamicResource ButtonStyle1}" /> <Button Content="B" Style="{DynamicResource ButtonStyle1}" /> <Button Content="C" Style="{DynamicResource ButtonStyle1}" /> <Button Content="D" Style="{DynamicResource ButtonStyle1}" /> <Button Content="E" Style="{DynamicResource ButtonStyle1}" /> <Button Content="F" Style="{DynamicResource ButtonStyle1}" /> </WrapPanel>--> </Expander> What's even more confusing is I can do
// ChartBarParent is the name of the custom control set in XAML ChartBarParent.Content = new TestControlWithContent(); and it works as well as fires the callback.
Ultimately, is UIElement in a dependency property and using a ContentPresenter the right way to do this?
ContentPresenteris meant to be used in aControlTemplate, and you populate its content not by binding itsContentproperty, but by setting itsContentSourceproperty to the name of a property on the templated parent (ContentSourcehas a default value of"Content", which is why you can often drop one in with no attributes and it magically Does What You Mean). If that specific usage doesn't apply to what you're doing, do as @ibebbs suggests and useContentControlinstead.ExpanderContentshould be of typeObject, same asContentControl.Content,ContentPresenter.Content. or whatever.