OnApplyTemplate not called in Custom Control

前端 未结 6 2049
忘掉有多难
忘掉有多难 2021-02-01 21:47

I have a Custom Control which uses some PART controls:

 [TemplatePart(Name = \"PART_TitleTextBox\", Type = typeof(TextBox))]
    [TemplatePart(Name = \"PART_Titl         


        
相关标签:
6条回答
  • 2021-02-01 22:25

    For anyone else who might stumble upon this post, I was having the same issue and I managed to solve it by adding the following into the AssemblyInfo.cs of the project containing my custom control:

    [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)
    )]
    

    My control's template is located in the file Theme/Generic.xaml in the same project as the control.

    0 讨论(0)
  • 2021-02-01 22:31

    Answer of @MoMo is correct, but additionally:

    E: It is expected that the Themes/Generic.xaml is in the root of your project. If this is not the case and your Generic.xaml is not in the root then you have to create a directory Themes with Generic.xaml in the root (Generic.xaml is just of type ResourceDictionary). In that Generic.xaml you need to reference to the location of your Generic.xaml.

    e.g.:

    <ResourceDictionary Source="/Foo.Bar;component/Controls/FooControl/Themes/Generic.xaml" />

    0 讨论(0)
  • 2021-02-01 22:37

    beside all mentioned above which is correct and you should check for,

    actually OnApplayTemplete() is called but after all property changed calls and I don't know why, it should be called first thing

    so if you are using your PARTs names to get element it will get errors because wpf will not find until OnApplayTemplete() called so, you must add if (your part element != null) condition in front of any code depend on the PARTs names

    then inside OnApplayTemplete() method it self recall all your logical method again and it will work fine

        TextBox textBox;
        public override void OnApplyTemplate()
                {
                    base.OnApplyTemplate();
                    //onther way to get elements & PARTs
                    textBox= Template.FindName("PART_TitleTextBox", this) as TextBox;
    
                    MyMethod();
        
                }
        private void MyMethod()
        {
    if (textBox == null) return;
    //your logical code here
        }
    
    0 讨论(0)
  • 2021-02-01 22:38

    I am going to add my own answer because both the above answers are incomplete as I have been struggling with this problem for some time now.

    As said by MoMo and Kai G above:

    A. The controls template and styles should be located in the Generic.xaml file a folder called Themes of the root of your project.

    B. Make sure your namespaces are correct in the Generic.xaml

    C. Set the style key in the constructor of your control.

    D. Ensure the theme attribute is in the assemblyinfo.cs file

    BUT you also need to ensure that your Generic.xaml file is set for the Build Action as Page:Do Not copy.

    If you fail to do this or the value was somehow set to something other than this, the OnApplyTemplate() method will not be invoked.

    0 讨论(0)
  • 2021-02-01 22:43

    The other two answers are correct...but not complete. According to this post (and my experience of just resolving this issue) there are 4 things you need to check: (for some reason the code blocks in this post wouldn't stay formatted if I used numbers or dashes...so letters it is)

    A. The controls template and styles should be located in the Generic.xaml file a folder called Themes of the root of your project.

    B. Make sure your namespaces are correct in the Generic.xaml

    C. Set the style key in the constructor of your control. It is also widely recommended you put the following in a static constructor.

     static YourControl()
     {
          DefaultStyleKeyProperty.OverrideMetadata(typeof(YourControl), new FrameworkPropertyMetadata(typeof(YourControl)));
     }
    

    D. Ensure the following is in your assemblyinfo.cs

     [assembly: ThemeInfo(ResourceDictionaryLocation.None, 
     //where theme specific resource dictionaries are located
     //(used if a resource is not found in the     
     // 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)
     )]
    
    0 讨论(0)
  • 2021-02-01 22:48

    I can't see your constructor, but don't forget to set the DefaultStyleKey:

    DefaultStyleKeyProperty.OverrideMetadata(typeof(TitleBoxNew), new FrameworkPropertyMetadata(typeof(TitleBoxNew)));
    
    0 讨论(0)
提交回复
热议问题