WPF错误:"无法向BarStaticItem类型的对象添加内容"

时间:2015-01-17 14:45:41

标签: wpf xaml wpf-controls datatemplate contenttemplate

我有这个XAML:

<dxb:BarStaticItem>
  <TextBlock Text="{Binding MyStatusBarText}"></TextBlock>
</dxb:BarStaticItem> 

但是,我收到了这个错误:

Cannot add content to an object of type BarStaticItem

如何修复此问题,以便我可以更改渲染项目的颜色和样式等内容?

2 个答案:

答案 0 :(得分:4)

假设BarStaticItemUserControl ...

我在一个部分cs文件中使用了代码,其中(几乎)所有内容都已完成,ObservableCollection代替UIElement(或您想要的任何元素)

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

using System.Collections.ObjectModel; // ObservableCollection.
using System.Collections.Specialized; // NotifyCollectionChangedEventHandler.
using System.Windows.Markup; // [ContentProperty()]

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

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

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

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

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

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

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

<UserControl ...>
    <Grid 
        x:Name="MyChildContainer"><!-- HERE ! -->
    </Grid>
</UserControl>

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

<dxb:BarStaticItem>
    <TextBlock Text="{Binding MyStatusBarText}"></TextBlock>
</dxb:BarStaticItem>

..并且TextBlock将落在Grid中定义并命名为MyChildContainer的{​​{1}}。您可以使用DockPanel或StackPanel,甚至根据{Element}中的类型或更新(依赖关系)属性决定子元素将在哪个容器中运行,如:

BarStaticItem.xaml
  

你是谁DV你不是我

答案 1 :(得分:-1)

这个XAML可以正常工作,但是它的限制(它不允许你按要求设置显示文本的颜色):

<dxb:BarStaticItem
    Content="{Binding MyStatusBarText}">
</dxb:BarStaticItem> 

此特定控件允许我们设置ContentTemplate。我们可以使用它来设置内容的样式:

<dxb:BarStaticItem
   ContentTemplate="????">
</dxb:BarStaticItem>   

首先,我们在DataTemplate中定义Window.Resources。这就是我们的ContentTemplate将指出的内容:

<Window.Resources>
    <DataTemplate x:Key="MyStatusBarContentTemplate">
        <!-- As the DataContext of a resource does not default to the window, we have to use RelativeSource to find the window. -->
        <TextBlock Name="MyText"                
            Text="{Binding Path=MyStatusBarText, 
            RelativeSource={RelativeSource Mode=FindAncestor,
            AncestorType=Window}}">                
        </TextBlock>
    </DataTemplate>
</Window.Resources>

由于DataContext的{​​{1}}与XAML的其余部分不同,如果省略XAML DataTemplate,则绑定将无法正常工作。除此之外,我们所做的只是定义一个模板,该模板可用于呈现控件的内容。

然后,我们将控制权指向RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}

DataTemplate

现在我们已经定义了自定义数据模板,我们可以做任何我们想做的事情。例如,我们可以添加一个<dxb:BarStaticItem ContentTemplate="{DynamicResource MyStatusBarContentTemplate}"> </dxb:BarStaticItem> ,如果状态栏包含文本Converter(其他情况不可能,则为蓝色)。

此答案还说明了如何使用Error显示大多数控件的自定义内容。

<强>更新

不是在Window的资源中定义DataTemplate,而是将其定义为DataTemplate的资源。这会将相关项目保存在XAML中。

这个特殊的XAML意味着如果文本包含字符串BarStaticItem,状态栏文本会自动变为红色,状态栏文本会自动加上时间前缀。如果您希望我发布转换器的C#代码,请告诉我。

Error