如何将UserControl绑定到自定义控件的内容

时间:2016-08-31 13:14:35

标签: c# wpf xaml custom-controls dependency-properties

我正在尝试创建一个非常灵活的自定义控件。我试图实现的灵活性,以便能够将UserControl绑定到ExpanderContent Dependency属性,代码隐藏在代码段后面:

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();
    }
    .
    .
    .

我尝试在XAML中使用ContentPresenter,但它不起作用。我显然可以填充按钮,它可以工作,但这会通过绑定来破坏动态内容。

<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>

我能做什么更令人困惑

// ChartBarParent is the name of the custom control set in XAML
ChartBarParent.Content = new TestControlWithContent();

它可以解决回调问题。

最终,依赖属性中是UIElement并使用ContentPresenter正确的方法来执行此操作吗?

2 个答案:

答案 0 :(得分:1)

尝试将ContentPresenter更改为ContentControl。

此外,您可以将UserControl包装在DataTemplate中,并将其设置为ContentControl.ContentTemplate,允许您通过ContentControl.Content属性传递数据上下文。

答案 1 :(得分:0)

以下是我将如何做到这一点。它依赖于urlpatterns = [ url(r'^$', TemplateView.as_view(template_name='base.html'), name="home"), url(r'^(?P<user_url>[\w.-]+)/', include('imagestore.urls', namespace='imagestore')), url(r'^(?P<user_url>[\w.-]+)/', include('profiles.urls', namespace='profiles_username')), ] 是UI的东西(如下面“用法”中的第二个示例),或者是具有隐式SecondaryContent的viewmodel。我可以轻松添加DataTemplate属性,以便让消费者更明确地控制模板的发生方式。

ChartBar.cs

SecondaryDataTemplateSelector

public class ChartBar : ContentControl { static ChartBar() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ChartBar), new FrameworkPropertyMetadata(typeof(ChartBar))); } // Rather than ExpanderContent, we're inheriting ContentControl.Content for the // main control content. #region SecondaryContent Property public Object SecondaryContent { get { return (Object)GetValue(SecondaryContentProperty); } set { SetValue(SecondaryContentProperty, value); } } public static readonly DependencyProperty SecondaryContentProperty = DependencyProperty.Register("SecondaryContent", typeof(Object), typeof(ChartBar), new PropertyMetadata(null)); #endregion SecondaryContent Property #region IsExpanded Property // This is optional. I just know I'd end up wanting it. public bool IsExpanded { get { return (bool)GetValue(IsExpandedProperty); } set { SetValue(IsExpandedProperty, value); } } public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register("IsExpanded", typeof(bool), typeof(ChartBar), new PropertyMetadata(false)); #endregion IsExpanded Property } ,或者Themes/Generic.xaml中的App.xaml,或者其中一个包含的其他.xaml资源字典。

<Application.Resources>

用法:

<ControlTemplate x:Key="ChartBarDefaultTemplate" TargetType="local:ChartBar">
    <!-- 
    Use Binding/RelativeSource TemplatedParent on IsExpanded so it updates both ways, 
    or remove that attribute/binding if you're not bothering with the IsExpanded DP.
    -->
    <Expander 
        x:Name="expander" 
        Header="" 
        VerticalAlignment="Top" 
        Style="{DynamicResource ExpanderStyle1}"
        IsExpanded="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
        >
        <StackPanel Orientation="Vertical">
            <ContentPresenter />
            <ContentControl 
                Content="{TemplateBinding SecondaryContent}" 
                />
        </StackPanel>
    </Expander>
</ControlTemplate>

<Style TargetType="local:ChartBar">
    <Setter 
        Property="Template" 
        Value="{StaticResource ChartBarDefaultTemplate}" 
        />
</Style>