WPF 错误:“无法将内容添加到 BarStaticItem 类型的对象”

Con*_*ngo 0 wpf xaml datatemplate wpf-controls contenttemplate

我有这个 XAML:

<dxb:BarStaticItem>
  <TextBlock Text="{Binding MyStatusBarText}"></TextBlock>
</dxb:BarStaticItem> 
Run Code Online (Sandbox Code Playgroud)

但是,我收到此错误:

Cannot add content to an object of type BarStaticItem

我该如何解决这个问题,以便我可以执行诸如更改渲染项目的颜色和样式之类的操作?

Kar*_*hen 5

假设BarStaticItem是一个UserControl...

我在一个部分cs文件中使用代码,其中(几乎)所有事情都已完成,用一个ObservableCollectionofUIElement代替(或任何你想要的元素)

1)创建一个名为 的相关分部类BarStaticItem.Children.cs,然后添加所需的命名空间:

using System.Collections.ObjectModel; // ObservableCollection.
using System.Collections.Specialized; // NotifyCollectionChangedEventHandler.
using System.Windows.Markup; // [ContentProperty()]
Run Code Online (Sandbox Code Playgroud)

2)ContentProperty在部分类声明上方添加一个标志,然后添加您的Children属性声明:

namespace YourNamespace.SubNamespace
{
    [ContentProperty("Children")] // <- here !
    public partial class BarStaticItem
    // (This is the related BarStaticItem.Children.cs file)
    {
        /// <summary>
        /// Gets the Children Property of this BarStaticItem.
        /// </summary>
        public ObservableCollection<UIElement> Children { get; private set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

3) 现在在 cs 文件中的私有方法中创建 ObservableCollection 属性初始值设定项:

        private void RegisterChildrenObservation()
        {
            Children = new ObservableCollection<UIElement>();
            Children.CollectionChanged += 
                new NotifyCollectionChangedEventHandler(Children_CollectionChanged);
        }
Run Code Online (Sandbox Code Playgroud)

4) 在自定义 UI 元素的构造函数中调用该初始值设定项:

namespace YourNamespace.SubNamespace
{
    public partial class BarStaticItem : UserControl
    // (This is the base BarStaticItem.xaml.cs file)
    {
        public BarStaticItem()
        {
            InitializeComponent();
            RegisterChildrenObservation(); // <- here !
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

5)通过声明在初始化程序中调用的方法处理程序来处理 BarStaticItem.Children.cs 文件中 Children 集合的行为:

这只是简单的正式程序。一旦您理解了整个事情,您就会发现您可以使用它并创建比单独使用 xaml 能做的更多的场景。首先,这里只有两个状态真正重要:

  • NotifyCollectionChangedAction.Add
  • NotifyCollectionChangedAction.Remove

    private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
            {
                foreach (UIElement currentElement in e.NewItems)
                {
                    MyChildContainer.Children.Add(currentElement);
                }
                break;
            }
    
            case NotifyCollectionChangedAction.Move:
            {
                break;
            }
    
            case NotifyCollectionChangedAction.Remove:
            {
                foreach (UIElement currentElement in e.OldItems)
                {
                    MyChildContainer.Children.Remove(currentElement);
                }
                break;
            }
    
            case NotifyCollectionChangedAction.Replace:
            {
                break;
            }
    
            case NotifyCollectionChangedAction.Reset:
            {
                break;
            }
    
            default:
            {
                break;
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

6) 您即将完成,但您必须在 BarStaticItem.xaml 文件中创建并命名一个 UIElement 以包含添加的 UIElements :

<UserControl ...>
    <Grid 
        x:Name="MyChildContainer"><!-- HERE ! -->
    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

然后就完成了,您可以像您一样直接在 XAML 中将任何子元素添加到 BarStaticItem 中。

<dxb:BarStaticItem>
    <TextBlock Text="{Binding MyStatusBarText}"></TextBlock>
</dxb:BarStaticItem>
Run Code Online (Sandbox Code Playgroud)

..这TextBlock将落在.中Grid定义和命名的位置。您可以使用 DockPanel 或 StackPanel,甚至可以根据子元素的类型或更新(依赖项)属性来决定子元素将进入哪个容器,例如:MyChildContainerBarStaticItem.xamlNotifyCollectionChangedAction.Add

private void Children_CollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Add:
        {
            foreach (UIElement currentElement in e.NewItems)
            {
                if (currentElement.GetType() == typeof(TextBlock))
                {
                    TextBlock currentTextBlock = (TextBlock)currentElement;
                    // Manipulate your TextBlock...
                    HeaderTextBlockContainer.Children.Add(currentElement);
                }
                else if (currentElement.GetType() == typeof(Button))
                {
                    FooterButtonsDockPanel.Children.Add(currentElement);
                    DockPanel.SetDock(currentElement, Dock.Right);
                }
                else
                {
                    MainContentContainer.Children.Add(currentElement);
                }
                ContentDefined = true; // Custom Property.
            }
            //...
Run Code Online (Sandbox Code Playgroud)

谁DV你不是我