2

我构建了一个 xaml 类,然后意识到如果我想将它用作抽象基类,则必须在没有 xaml 的情况下构建它。但是当我完成将我的 xaml 转换为 C# 时,结果并没有输出相同的内容。

例如,前景不一样。(左侧为 ViewDialogX,右侧为 ViewDialogC)

xaml 与 c# 实例

ViewDialogX.xaml

<ContentControl x:Class="xmlns.ViewDialogX"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:my="clr-namespace:xmlns"
             HorizontalAlignment="Center" VerticalAlignment="Center">
    <ContentControl.Template>
        <ControlTemplate TargetType="my:ViewDialogX">
            <Border MinWidth="160" MinHeight="90" Margin="1,2,3,3" Padding="4">
                <Border.Effect>
                    <DropShadowEffect BlurRadius="10" Opacity="3" ShadowDepth="0" />
                </Border.Effect>
                <GroupBox Header="{TemplateBinding Title}" Background="{DynamicResource ControlBackgroundBrush}">
                    <Grid Width="{TemplateBinding ContentWidth}" Height="{TemplateBinding ContentHeight}">
                        <ContentPresenter Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" />
                    </Grid>
                </GroupBox>
            </Border>
        </ControlTemplate>
    </ContentControl.Template>
</ContentControl>

ViewDialogX.xaml.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 xmlns
{
    public partial class ViewDialogX : ContentControl
    {
        public ViewDialogX()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.RegisterAttached("Title", typeof(string), typeof(ViewDialogX), new PropertyMetadata(" "));
        public string Title { get { return (string)this.GetValue(TitleProperty); } set { this.SetValue(TitleProperty, value); } }

        public static readonly DependencyProperty ContentWidthProperty =
            DependencyProperty.RegisterAttached("ContentWidth", typeof(double), typeof(ViewDialogX), new PropertyMetadata(double.NaN));
        public double ContentWidth { get { return (double)this.GetValue(ContentWidthProperty); } set { this.SetValue(ContentWidthProperty, value); } }

        public static readonly DependencyProperty ContentHeightProperty =
            DependencyProperty.RegisterAttached("ContentHeight", typeof(double), typeof(ViewDialogX), new PropertyMetadata(double.NaN));
        public double ContentHeight { get { return (double)this.GetValue(ContentHeightProperty); } set { this.SetValue(ContentHeightProperty, value); } }

        public virtual void OnClosing(CancelEventArgs e) { }
        public virtual void Close() { }
    }
}

ViewDialogC.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 xmlns
{
    public class ViewDialogC : ContentControl
    {
        public ViewDialogC()
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                this.SetValue(ViewDialogC.HorizontalAlignmentProperty, HorizontalAlignment.Center);
                this.SetValue(ViewDialogC.VerticalAlignmentProperty, VerticalAlignment.Center);

                FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
                border.SetValue(Border.MinWidthProperty, 160d);
                border.SetValue(Border.MinHeightProperty, 90d);
                border.SetValue(Border.MarginProperty, new Thickness(1, 2, 3, 3));
                border.SetValue(Border.PaddingProperty, new Thickness(4));
                border.SetValue(Border.EffectProperty, new DropShadowEffect() { BlurRadius = 10, Opacity = 3, ShadowDepth = 0 });
                FrameworkElementFactory group = new FrameworkElementFactory(typeof(GroupBox));
                group.SetValue(GroupBox.HeaderProperty, new TemplateBindingExtension(ViewDialogC.TitleProperty));
                group.SetResourceReference(GroupBox.BackgroundProperty, "ControlBackgroundBrush");
                FrameworkElementFactory grid = new FrameworkElementFactory(typeof(Grid));
                grid.SetValue(Grid.WidthProperty, new TemplateBindingExtension(ViewDialogC.ContentWidthProperty));
                grid.SetValue(Grid.HeightProperty, new TemplateBindingExtension(ViewDialogC.ContentHeightProperty));
                FrameworkElementFactory content = new FrameworkElementFactory(typeof(ContentPresenter));
                content.SetValue(ContentPresenter.MarginProperty, new TemplateBindingExtension(ViewDialogC.PaddingProperty));
                content.SetValue(ContentPresenter.ContentProperty, new TemplateBindingExtension(ViewDialogC.ContentProperty));
                grid.AppendChild(content);
                group.AppendChild(grid);
                border.AppendChild(group);
                this.SetValue(ViewDialogC.TemplateProperty, new ControlTemplate(typeof(ViewDialogC)) { VisualTree = border });
            }
        }

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.RegisterAttached("Title", typeof(string), typeof(ViewDialogC), new PropertyMetadata(" "));
        public string Title { get { return (string)this.GetValue(TitleProperty); } set { this.SetValue(TitleProperty, value); } }

        public static readonly DependencyProperty ContentWidthProperty =
            DependencyProperty.RegisterAttached("ContentWidth", typeof(double), typeof(ViewDialogC), new PropertyMetadata(double.NaN));
        public double ContentWidth { get { return (double)this.GetValue(ContentWidthProperty); } set { this.SetValue(ContentWidthProperty, value); } }

        public static readonly DependencyProperty ContentHeightProperty =
            DependencyProperty.RegisterAttached("ContentHeight", typeof(double), typeof(ViewDialogC), new PropertyMetadata(double.NaN));
        public double ContentHeight { get { return (double)this.GetValue(ContentHeightProperty); } set { this.SetValue(ContentHeightProperty, value); } }

        public virtual void OnClosing(CancelEventArgs e) { }
        public virtual void Close() { }
    }
}

实现xml代码:

    <my:ViewDialogX Title="Test">
        <Button Content="Button" />
    </my:ViewDialogX>
    <my:ViewDialogC Title="Test">
        <Button Content="Button" />
    </my:ViewDialogC>

额外样式:

<SolidColorBrush x:Key="ControlBackgroundBrush" Color="#333333" />
<SolidColorBrush x:Key="NormalBackgroundBrush" Color="#595959" />
<LinearGradientBrush x:Key="ShineBrush" StartPoint="0,0.042" EndPoint="0,0.971">
    <GradientStop Color="#59FFFFFF" Offset="0" />
    <GradientStop Color="#26FFFFFF" Offset="0.467" />
    <GradientStop Color="#00FFFFFF" Offset="0.475" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="HoverShineBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="#4CFFFFFF" Offset="0" />
    <GradientStop Color="#26FFFFFF" Offset="0.467" />
    <GradientStop Color="#10FFFFFF" Offset="0.475" />
    <GradientStop Color="#10FFFFFF" Offset="0.856" />
    <GradientStop Color="#26FFFFFF" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#ADADAD" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#787878" />
<SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />
<Style TargetType="{x:Type GroupBox}" BasedOn="{x:Null}">
    <Setter Property="Background" Value="{x:Null}" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="BorderBrush" Value="{DynamicResource ControlBackgroundBrush}" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="Padding" Value="3" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type GroupBox}">
                <DockPanel>
                    <Grid x:Name="HeaderGrid" DockPanel.Dock="Top">
                        <Border x:Name="BackgroundElement" Background="{DynamicResource NormalBackgroundBrush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" />
                        <Border x:Name="ShineElement" Background="{DynamicResource ShineBrush}" BorderThickness="0" Margin="1" CornerRadius="3" />
                        <Border x:Name="ShineBorderElement" BorderBrush="{DynamicResource HoverShineBrush}" BorderThickness="1" CornerRadius="2" Margin="{TemplateBinding BorderThickness}" />
                        <ContentPresenter x:Name="ContentElement" SnapsToDevicePixels="True" ContentSource="Header"  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4" RecognizesAccessKey="True" />
                    </Grid>
                    <Border DockPanel.Dock="Bottom" Margin="0,-1,0,0" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3">
                        <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="{TemplateBinding Padding}" />
                    </Border>
                </DockPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}" />
                        <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="BackgroundElement" />
                        <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="ShineBorderElement" />
                        <Setter Property="Opacity" TargetName="HeaderGrid" Value="0.75" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的问题再次是:为什么 ViewDialogX 和 ViewDialogC 的输出不一样?

(不知何故 ViewDialogC 正在编辑组框的前景。)

编辑:

我在这条线上找到了前景变化的原因:

group.SetResourceReference(GroupBox.BackgroundProperty, "ControlBackgroundBrush");

(请参阅 ViewDialogX.xaml 了解我想要实现的目标)

我可以将背景硬设置为特定颜色,甚至可以将其绑定到模板父属性,但是当 FrameworkElementFactory 获取属性的动态资源类型时,前景会从 TemplateParent 继承。这是一个错误吗?

4

1 回答 1

2

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

我对这个示例的解决方法:使用另一个控件来调用 *.SetResourceReference 并绘制背景,而不是使用 GroupBox。

于 2012-10-21T19:28:53.927 回答