Aquí es donde entra en juego TemplateBinding (TemplateBinding se usa dentro de las plantillas de control y se usa para recuperar valores del control de plantilla, en este caso el Botón).
<Ellipse Fill="LightGreen"
Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}"/>
Tenga en cuenta que esta es una forma más corta de utilizar:
{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}
La extensión de marcado TemplateBinding es sólo optimizado para sólo fijaciones TemplatedParent.
Dicho esto, si quisieras que fuera solo un círculo, si tu elipse fuera menor que la W/H, entonces tu contenido fluirá fácilmente, lo que dudo es lo que realmente deseas ...? Pensé en usar un convertidor multivalor para hacer eso, pero no se puede vincular al parámetro del convertidor, así que eso está fuera.
En ese caso, un comportamiento adjunto funcionaría, pero no es bonito.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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="{TemplateBinding ActualWidth}" local:ConstrainWidthHeight.ConstrainedHeight="{TemplateBinding ActualHeight}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
... y el comportamiento adjunto:
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;
}
}
}
}
}
bien, ahora la razón de por qué el uso se requiere un comportamiento adjunto (AFAICT de todos modos), es que con el fin de centrar la elipse (en una escenario no cuadrado/no circular), necesita la Alineación Horizontal y la Alineación Vertical para poder tener efecto. El valor predeterminado de ambos es Estirar, y cuando se establece un Ancho/Alto explícito, se comporta como Centro.
Con Estirar = "Uniforme" activado, su Elipse siempre ocupará físicamente todo el espacio, solo el dibujo de la Elipse quedará restringido. Usando esto, tu figura de Elipse dibujada siempre comenzará en la esquina superior izquierda. Entonces, en este caso, si su botón es más ancho que alto, la parte dibujada de la elipse no se centrará junto con el texto.
Este código es un buen ejemplo de lo que es probable que no buscas:
<Ellipse Height="{TemplateBinding ActualHeight}" Width="{TemplateBinding ActualWidth}" Fill="LightGreen" Stretch="Uniform" />
... y el botón de usarlo (con una anchura/altura no cuadrados):
<Button Content="YO!" Style="{StaticResource Button2}" Width="120" Height="53" VerticalAlignment="Top"></Button>
se ve así:
Ugly http://www.freeimagehosting.net/uploads/84e62c4982.png
...en comparación con esto con la opción de propiedad adjunta:
alt text http://www.freeimagehosting.net/uploads/40755babcd.png
bien he intentado este método y parece aplicar HorizontalAlignment = "centro" VerticalAlignment = "centro" de la elipse también hace que la forma del círculo desaparece después de cambiar el tamaño de un gran tamaño. Me pregunto qué está pasando. – icelava
Actualicé mi respuesta para usar ActualWidth y ActualHeight. La vinculación a W/H es la razón por la que está haciendo lo que está viendo. –
Después de cambiar a ActualWidth y ActualHeight, parece renderizarse en el centro ahora. Aunque todavía no entiendo completamente por qué, gracias. – icelava