WPF: GroupBox.SetResourceReference suddenly makes it inherit TemplateParent.Foreground

StackOverflow https://stackoverflow.com/questions/12900991

  •  07-07-2021
  •  | 
  •  

Pergunta

I was making a UserControl when I found this strange phenomena. If I use C# code to place a GroupBox in the UserControl's template and then make any SetResourceReference call on the GroupBox, suddenly the GroupBox inherits the foreground of TemplateParent (my UserControl).

So far I have found the following requirements for this situation:

  • UserControl base type does not matter
  • Affected template child must be a GroupBox (but not necessarily the first template child)
  • The foreground of the GroupBox may be explicitly set in the template, overriding the inherit
  • Must be using some sort of reference call from the GroupBox
  • Only the Foreground property seems to be affected

Here is my sample code:

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="350">
    <Window.Resources>
        <Thickness x:Key="TestPadding">5</Thickness>
        <Style TargetType="{x:Type GroupBox}">
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="Background" Value="Orange" />
        </Style>
    </Window.Resources>
    <Grid>
        <my:TestControl Foreground="Blue" Background="Purple" />
    </Grid>
</Window>

TestControl.cs:

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Markup;

namespace WpfApplication1
{
    public class TestControl : UserControl
    {
        public TestControl()
        {
            FrameworkElementFactory group = new FrameworkElementFactory(typeof(GroupBox));
            group.SetValue(GroupBox.ContentProperty, "My Child");
            group.SetResourceReference(GroupBox.MarginProperty, "TestPadding");
            this.SetValue(TestControl.TemplateProperty, new ControlTemplate(typeof(TestControl)) { VisualTree = group });
        }
    }
}


What do you guys think, is this a bug that I should report to Microsoft?

Foi útil?

Solução 2

I have contacted the Microsoft WPF Development Team. They acknowledge this as a bug, but have prioritised it as low and not likely to be fixed.

My work around for this example: Use another control to take the *.SetResourceReference call to perform padding, instead of the GroupBox.

Outras dicas

I don't think that is a Microsoft issue. In fact i think it works fine. You are defining a Templeate in code behinde for your TestControl, and you are setting a GroupBox as root element for the template. What happens here is that your UserControl.Foreground property is not the same that the GroupBox that is the root of your template, then the GroupBox (as GroupBox) will take the Foreground that inherits from the Resources (in this case Window's Resources).

If you want to solve this, you can do something like "TemplateBindings", the follow code will works for you like a TemplateBinding:

namespace WpfApplication1
{
    public class TestControl : UserControl
    {
        public TestControl()
        {
            FrameworkElementFactory group = new FrameworkElementFactory(typeof(GroupBox));
            group.SetValue(GroupBox.ContentProperty, "My Child");
            group.SetResourceReference(GroupBox.MarginProperty, "TestPadding");

            //This line will work as a TeplateBinding
            group.SetBinding(GroupBox.ForegroundProperty, new Binding() { Path = new PropertyPath("Foreground"), RelativeSource = RelativeSource.TemplatedParent });

            this.SetValue(TestControl.TemplateProperty, new ControlTemplate(typeof(TestControl)) { VisualTree = group });
        }
    }
}

Hope this answer will be useful for you.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top