我构建了一个 xaml 类,然后意识到如果我想将它用作抽象基类,则必须在没有 xaml 的情况下构建它。但是当我完成将我的 xaml 转换为 C# 时,结果并没有输出相同的内容。
例如,前景不一样。(左侧为 ViewDialogX,右侧为 ViewDialogC)
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 继承。这是一个错误吗?