Моя задача
Создайте UserControl
, который должен содержать любой визуальный дочерний элемент, доступный в WPF, дети отображаются в контейнере, который является дочерним элементом UserControl
.
Моя проблема
Мне не удается правильно отобразить изображения в моем контейнере, я пробовал использовать сервале и не нашел способ, который работает в дизайнере. Я также попытался использовать ContentControl
, но ничего не отображается.
Мои подходы
Сначала я нашел эту ссылку, и я попробовал ее с некоторыми вариантами. Мне удалось отобразить содержимое в правом контейнере, но оно не работает в дизайнере, потому что свойство content задано как private, и разработчик хочет его переопределить. Размещение всего в XAML работает, но это плохо при работе с дизайнерами. Это может быть любимым способом.
После этого я попытался использовать ContentControl
, привязывая его Content
-property к связующему свойству типа UIElementCollection
. Этот aproach не вызывает ошибок в дизайнере, но я должен признать, что я никогда не вижу никакого контроля (например, Button
) в моем контейнере. Он остается пустым, но добавлены дети.
Заключение
После того, как часы сервлетов искали легкое и быстрое решение, я решил попросить решения здесь. Я немного разочарован. Было бы очень полезно, если бы Microsoft могла получить образец в MSDN.
Я уверен, что должен быть простой способ архивировать это.
Текущая ситуация
Благодаря Андрею Гаврила и jberger я архивируются, чтобы создать node, который отображает содержимое (см. код ниже), но есть еще две проблемы: - Нет поддержки дизайнеров - Граница (см. Xaml) не отображается в дизайнере и не отображается, когда приложение работает, даже нет поля
public class NodeContent : ContentControl
{
static NodeContent()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NodeContent), new FrameworkPropertyMetadata(typeof(NodeContent)));
}
}
public partial class Node : UserControl, INotifyPropertyChanged
{
UIElementCollection _Elements;
public event PropertyChangedEventHandler PropertyChanged;
public UIElementCollection NodeContent
{
get { return _Elements; }
set
{
_Elements = value;
OnPropertyChanged("NodeContent");
}
}
public Node()
{
InitializeComponent();
NodeContent = new UIElementCollection(NodeContentContainer, this);
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
Node -Xaml:
<UserControl x:Class="Pipedream.Nodes.Node"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="216" d:DesignWidth="174" Background="Transparent" Name="NodeControl" xmlns:my="clr-namespace:Pipedream.Nodes">
<Border BorderThickness="1" CornerRadius="20" BorderBrush="Black" Background="White">
<Grid>
<my:NodeContent x:Name="NodeContentContainer" Margin="20" Content="{Binding Source=NodeControl, Path=NodeContent}" />
</Grid>
</Border>
</UserControl>
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:Pipedream.Nodes">
<Style TargetType="{x:Type local:NodeContent}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Node}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>