这就是TemplateBinding的作用(TemplateBinding在控件模板中使用,用于从模板化控件中检索值,例如Button)。
<Ellipse Fill="LightGreen"
Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}"/>
请注意,这是使用较短的形式:
{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}
模板绑定标记扩展仅针对TemplatedParent绑定进行了优化。
也就是说,如果您只想让它成为一个圆形,如果您的椭圆形是W/H中较小的那个,则您的内容将很容易流出去,我怀疑这不是您真正想要的...?我曾考虑使用多值转换器来实现,但您不能绑定到转换器参数,因此无法实现。
在这种情况下,附加行为将起作用,但并不美观。
<Window x:Class="WpfApplication1.Window1"
xmlns="http:
xmlns:x="http:
xmlns:c="clr-namespace:WpfApplication1"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Content="Yo!" Width="50" Height="30">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="LightGreen" local:ConstrainWidthHeight.ConstrainedWidth="" local:ConstrainWidthHeight.ConstrainedHeight=""/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
...以及附加的行为:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
namespace WpfApplication1 {
public class ConstrainWidthHeight {
public static readonly DependencyProperty ConstrainedWidthProperty =
DependencyProperty.RegisterAttached( "ConstrainedWidth", typeof( double ), typeof( ConstrainWidthHeight ), new PropertyMetadata( double.NaN, OnConstrainValuesChanged ) );
public static readonly DependencyProperty ConstrainedHeightProperty =
DependencyProperty.RegisterAttached( "ConstrainedHeight", typeof( double ), typeof( ConstrainWidthHeight ), new UIPropertyMetadata( double.NaN, OnConstrainValuesChanged ) );
public static double GetConstrainedHeight( FrameworkElement obj ) {
return (double) obj.GetValue( ConstrainedHeightProperty );
}
public static void SetConstrainedHeight( FrameworkElement obj, double value ) {
obj.SetValue( ConstrainedHeightProperty, value );
}
public static double GetConstrainedWidth( FrameworkElement obj ) {
return (double) obj.GetValue( ConstrainedWidthProperty );
}
public static void SetConstrainedWidth( FrameworkElement obj, double value ) {
obj.SetValue( ConstrainedWidthProperty, value );
}
private static void OnConstrainValuesChanged( object sender, DependencyPropertyChangedEventArgs e ) {
FrameworkElement element = sender as FrameworkElement;
if( element != null ) {
double width = GetConstrainedWidth( element );
double height = GetConstrainedHeight( element );
if( width != double.NaN && height != double.NaN ) {
double value = Math.Min( width, height );
element.Width = value;
element.Height = value;
}
}
}
}
}
好的,现在使用一个附加行为所需的原因是(据我所知),为了使椭圆居中(在非正方形/非圆形场景中),需要使HorizontalAlignment和VerticalAlignment生效。两者的默认值都为Stretch,当明确设置宽度/高度时,它的行为就像是居中。
在Stretch =“Uniform”时,您的椭圆形始终会真实地占用整个空间,只有椭圆形的绘制会受到限制。使用这种方式,您绘制的椭圆形图形始终从左上角开始。因此,在此情况下,如果您的按钮比高更宽,则椭圆形的绘制部分不会与文本一起居中。
此代码是您可能不需要的好示例:
<Ellipse Height="{TemplateBinding ActualHeight}" Width="{TemplateBinding ActualWidth}" Fill="LightGreen" Stretch="Uniform" />
...和使用它的按钮(具有非正方形的宽度/高度):
<Button Content="YO!" Style="{StaticResource Button2}" Width="120" Height="53" VerticalAlignment="Top"></Button>
看起来像这样:
丑陋的 http://www.freeimagehosting.net/uploads/84e62c4982.png
... 与使用附加属性选项相比,变成了这个样子:
alt 文本 http://www.freeimagehosting.net/uploads/40755babcd.png