1

当我发现这个奇怪的现象时,我正在制作一个 UserControl。如果我使用 C# 代码在 UserControl 的模板中放置一个 GroupBox,然后在 GroupBox 上进行任何 SetResourceReference 调用,那么 GroupBox 突然继承了 TemplateParent(我的 UserControl)的前景。

到目前为止,我已经找到了针对这种情况的以下要求:

  • UserControl 基本类型无关紧要
  • 受影响的模板子必须是 GroupBox(但不一定是第一个模板子)
  • GroupBox 的前景可以在模板中显式设置,覆盖继承
  • 必须使用来自 GroupBox 的某种引用调用
  • 只有 Foreground 属性似乎受到影响

这是我的示例代码:

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>

测试控制.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 });
        }
    }
}


你们怎么看,这是我应该向微软报告的错误吗?

4

2 回答 2

0

我不认为这是微软的问题。事实上,我认为它工作正常。您正在为您的 TestControl 在代码后面定义一个模板,并且您正在将一个 GroupBox 设置为模板的根元素。这里发生的情况是您的 UserControl.Foreground 属性与作为模板根的 GroupBox 不同,然后 GroupBox(作为 GroupBox)将采用从资源(在本例中为窗口的资源)继承的前景。

如果你想解决这个问题,你可以做一些类似“TemplateBindings”的事情,下面的代码会像 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 });
        }
    }
}

希望这个答案对你有用。

于 2012-10-16T12:31:35.853 回答
0

我已联系 Microsoft WPF 开发团队。他们承认这是一个错误,但将其列为低优先级并且不太可能修复。

我对这个示例的解决方法:使用另一个控件来执行 *.SetResourceReference 调用来执行填充,而不是 GroupBox。

于 2012-10-21T19:25:13.753 回答