支持WPF自定义控件和直接内容

问题描述 投票:1回答:4

我是一个相当新的WPF,并有点卡,所以任何帮助将被感激。

我试图编写WPF自定义控件,它封装了我已经有的几个功能元素(即排序、过滤、标准菜单等),但在一个漂亮的整洁的包中,以避免重复。

总之,我已经创建了自定义控件(基于控件),然后在Generic.Xaml中添加了以下内容。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Controls.ListViewExtended">
    <Style TargetType="{x:Type local:ListViewExtended}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ListViewExtended}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <ListView>
                            <ListView.View>
                                <GridView>
                                <!-- Content goes here -->                             
                                </GridView> 
                            </ListView.View>
                        </ListView>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

当我尝试添加GridViewColumns(或任何控件),如下图所示......。

<elv:ListViewExtended>
   <GridView>
        <GridViewColumn Width="140" Header="Column 1" />
        <GridViewColumn Width="140" Header="Column 2" />
        <GridViewColumn Width="140" Header="Column 3" />
   </GridView>
</elv:ListViewExtended>

我得到的是 "......不支持直接内容" 错误。

我已经创建了一个依赖属性(同样在下面),允许添加GridView,但还是不行。

public static DependencyProperty GridViewProperty;

public static string GridViewHeader(DependencyObject target) 
{
    return (string)target.GetValue(GridViewProperty); 
}
public static void GridViewHeader(DependencyObject target, string value) 
{
    target.SetValue(GridViewProperty, value); 
} 

先谢谢你

wpf wpf-controls
4个回答
2
投票

继承您的自定义控件 ListView,而不是来自 Control. 这肯定会导致你改变模板,但我鼓励你阅读更多关于如何做的文档(例如Sacha Barber的文章。创建和消费一个自定义的WPF控件).

祝您学习愉快!


18
投票

您只需指定ContentPropertyAttribute即可。

[ContentProperty("MainContent")]
public class GroupPanel : Control
{
    public GroupPanel()
    {
        DefaultStyleKey = typeof(GroupPanel);
    }

    public object MainContent
    {
        get { return GetValue(MainContentProperty); }
        set { SetValue(MainContentProperty, value); }
    }

    public static readonly DependencyProperty MainContentProperty =
        DependencyProperty.Register("MainContent", typeof(object), typeof(GroupPanel), null);
}

参考。http:/msdn.microsoft.comen-uslibrarysystem.windows.markup.contentpropertyattribute(v=vs.90).aspx。


6
投票

我在我们的项目中使用这个简单的解决方案来支持自定义控件中的直接内容。

在你的项目中添加一个 "CustomControl",并从 "UserControl "类中派生出这个控件,而不是 "Control"。

public class MyCustomControl: UserControl
{
    static MyCustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), 
            new FrameworkPropertyMetadata(typeof(MyCustomControl)));
    }
}

当你在项目中添加一个自定义控件时,Visual Studio(我使用的是2012年)会自动添加一个文件夹 "Themes",其中包括一个名为 "Generic.xaml "的文件。这个文件中包含一个资源字典,用于定义自定义控件的样式(模板)。

你会发现你的CustomControl的基本模板,已经作为DefaultStyle使用。为了支持直接的内容,请在这个模板中的某个地方放置一个具有父内容绑定的ContentPresenter。

<Style TargetType="{x:Type local:MyCustomControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyCustomControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

现在,您就可以向您的CustomControl添加内容了。

<Window x:Class="MyApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:MyApplication"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <controls:MyCustomControl>
                <TextBlock>Hello</TextBlock>
        </controls:MyCustomControl>
    </Grid>
</Window>

希望这对你有帮助


0
投票

不要使用

{Binding MainContent ElementName=Self}

使用

Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MainContent}" />

本来可以帮我省下这么多时间的。

© www.soinside.com 2019 - 2024. All rights reserved.