0xbadf00d
0xbadf00d

Reputation: 18228

WPF OnApplyTemplate on derived class of ItemsControl isn't called

The title basically points it out. I've read other blogs and posts related to the same issue, but none of the provided solutions did work for me.

Here's a simplification of my code:

<!-- CustomItemsControl.xaml -->
<ItemsControl x:Class="myNamespace.CustomItemsControl"
              xmlns:local="clr-namespace:myNamespace">

    <ItemsControl.Resources>    
        <Style TargetType="{x:Type local:CustomItemsControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:CustomItemsControl}">
                        <Grid x:Name="MyItemsHost" Background="{TemplateBinding Background}" IsItemsHost="True"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.Resources>
</ItemsControl>

// CustomItemsControl.xaml.cs
namespace myNamespace
{
    public partial class CustomItemsControl : ItemsControl
    {
        public CustomItemsControl()
        {
            this.DefaultStyleKey = typeof(CustomItemsControl);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var MyItemsHost = (Grid)base.GetTemplateChild("MyItemsHost");
        }
    }
}

What I'm doing wrong?

Upvotes: 1

Views: 2501

Answers (2)

FunkMonkey33
FunkMonkey33

Reputation: 2248

Depending on what your Custom Control derives from, you may not be able to call InitializeComponent() on it. For example, a ContentControl doesn't provide InitializeComponent.

If you check this thread, you'll see that the reason OnApplyTemplate never gets called, is because you defined the project as a Class Library, not a Custom Control Library. Visual Studio adds extra information to AssemblyInfo.cs to tell the runtime where to find the template for your control.

If you add the following code to your AssemblyInfo.cs file, it should start behaving correctly:

[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page, 
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page, 
// app, or any theme specific resource dictionaries)

)]

Upvotes: 1

Kris
Kris

Reputation: 7170

I haven't seen it done that way before, I define the template in Generic.xaml as that is what Visual Studio generates when you go Project->Add Custom Control (WPF).

You can make the code you posted work by calling InitializeComponent(); in your constructor. Also the documentation says you should use Template.FindName("MyItemsHost",this) instead of GetTemplateChild. If your control may need a different layout other than the grid you may want to use an ItemsPresenter and set the ItemsPanelTemplate instead.

Upvotes: 1

Related Questions