使自定义WPF控件设计器友好

时间:2017-05-10 18:04:01

标签: c# wpf visual-studio wpf-controls

我创建了一个自定义控件(通过扩展System.Windows.Control.Control)并使用Generic.xaml

设置样式

这很有效,但到目前为止我发现设计友好的唯一方法是添加ContentPropertyAttribute来指定哪个属性包含(主要)内容。

Designer允许我与此内容进行交互,就好像它是一个布局(例如,您可以在Designer预览中的内容中单击以选择某些内容)

但是我的控件需要有多个内容区域。

这些附加区域与Designer不兼容。您可以在xaml中指定内容并且显示正确,但您无法与其进行交互。

有没有办法让Designer支持多个内容属性?

编辑:以下是我的控件使用情况的示例:

<my:MyControl>
  <my:MyControl.HeaderContent>
    <TextBlock Text="Content for Header" />
  </my:MyControl.HeaderContent>
  <my:MyControl.FooterContent>
    <TextBlock Text="Content for Footer" />
  </my:MyControl.FooterContent>
  <TextBlock Text="Main Content (annotated with [ContentProperty])">
</my:MyControl>

EDIT2:这是一个简短的工作示例

如果你想尝试一下,只需创建一个新的Wpf应用程序并添加这两个文件并修改MainWindow.xaml。

主题/ 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:WpfApp1">
    <Style TargetType="{x:Type local:MyControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MyControl}">
                    <Border BorderThickness="3"  BorderBrush="Blue" CornerRadius="5" Background="White" Padding="5">
                        <DockPanel LastChildFill="True">
                            <Border DockPanel.Dock="Top" BorderThickness="3" BorderBrush="Red" CornerRadius="5" Padding="5">
                                <ContentPresenter Content="{TemplateBinding HeaderContent}"  />
                            </Border>
                            <Border BorderThickness="3" BorderBrush="Green" CornerRadius="5" Padding="5">
                                <ContentPresenter Content="{TemplateBinding Content1}" />
                            </Border>
                        </DockPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

MyControl.cs:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;

namespace WpfApp1
{
    [ContentProperty("Content1")]
    public class MyControl : Control
    {
        static MyControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl),
                   new FrameworkPropertyMetadata(typeof(MyControl)));
        }

        public static readonly DependencyProperty HeaderContentProperty =
             DependencyProperty.Register("HeaderContent", typeof(object),
             typeof(MyControl), null);

        public static readonly DependencyProperty Content1Property =
             DependencyProperty.Register("Content1", typeof(object),
             typeof(MyControl), null);


        public object HeaderContent
        {
            get { return GetValue(HeaderContentProperty); }
            set
            {
                SetValue(HeaderContentProperty, value);
               // HeaderContentHost.Content = value;
            }
        }
        public object Content1
        {
            get { return GetValue(Content1Property); }
            set {
                SetValue(Content1Property, value);
                //ContentHost.Content = value;
            }
        }
    }
}

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <local:MyControl>
        <local:MyControl.HeaderContent>
            <Label Background="BlueViolet" Height="100" >
                HeaderContent
            </Label>
        </local:MyControl.HeaderContent>
        <local:MyControl.Content1>
            <Label Background="Yellow">
                Main Content
            </Label>
        </local:MyControl.Content1>
    </local:MyControl>
</Window>

重点是,如果在Visual设计器中打开MainWindow.xaml,则只能在Content1上进行交互,并且只有控件上的ContentProperty存在时才能进行交互。如果删除ContentProperty,则既不能与Content1交互,也不能与HeaderContent交互。

有没有人知道如何让这种控制更加设计友好?

0 个答案:

没有答案