Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
876 views
in Technique[技术] by (71.8m points)

wpf - Why Does ItemsControl Not Use My ItemTemplate?

I am able to use an ItemTemplate within an ItemsControl to render items in a specific format. However, if one of the items within the ItemsControl happens to be, say, a TextBox, that TextBox is rendered rather than an instance of the ItemsTemplate. From what I can tell, this is true for any FrameworkElement. Is this intended behavior for an ItemsControl, or am I doing something incorrectly?

An example:

<ItemsControl>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Grid Margin="5">
        <Rectangle Fill="Blue" Height="20" Width="20" />
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <ItemsControl.Items>
    <sys:Object />
    <TextBox />
    <sys:Object />
    <Rectangle Fill="Red" Height="20" Width="20" />
  </ItemsControl.Items>
</ItemsControl>

I expected this to display four blue rectangles. I thought that any time an ItemTemplate has been defined each item in the collection is rendered as an instance of the template. However, in this case the following is rendered: a blue rectangle followed by a TextBox followed by a blue rectangle followed by a red rectangle.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The ItemsControl has a protected member IsItemItsOwnContainerOverride which is passed an object from the items collection and returns true if that object can be added directly to the items panel without a generated container (and thereby be templated).

The base implementation returns true for any object that derives from UIElement.

To get the behaviour you would expect you would need to inherit from ItemsControl and override this method and have it always return false. Unfortunately thats not the end of the matter. The default implementation of PrepareContainerForItemOverride still doesn't assign the ItemTemplate to the container if the item is a UIElement so you need to override this method as well:-

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return false;
    }


    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);
        ((ContentPresenter)element).ContentTemplate = ItemTemplate;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...