wpf c#-4.0 controltemplate

wpf - Acceder a un control dentro de ControlTemplate



c#-4.0 (6)

Si puede obtener el control de la cuadrícula, intente usar el código siguiente

TextBlock textBlock2 = (TextBlock)gridInTemplate.Children[1];

Este es el xaml:

<Page.Resources> <ControlTemplate x:Key="WeddingButtonBigTemplate" TargetType="Button"> <Grid> <Image x:Name="imgNormal" Source="../Images/Married_button2.png"/> <TextBlock x:Name="textBlock2" Style="{StaticResource RegularBlueSpecialBoldText}" LineHeight="28" LineStackingStrategy="BlockLineHeight" HorizontalAlignment="Center" Margin="10,30,10,70" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Stretch" > <Run FontSize="20" Text="The event of"></Run> <Run FontSize="28" Text="{DynamicResource strBride}"></Run> </TextBlock> </Grid> </ControlTemplate> </Page.Resources> <Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1000"> <Button x:Name="btnWedding" HorizontalAlignment="Left" Margin="10,20,0,-49" VerticalAlignment="Top" Template="{StaticResource WeddingButtonBigTemplate}" Foreground="#FF2B4072" Width="380" Click="btnClick" /> </Grid>

Estoy tratando de obtener acceso al TextBlock llamado textBlock2 .
Intenté anular OnApplyTemplate pero obtuve el valor nulo.

He intentado:

Grid gridInTemplate = (Grid)btnWedding.Template.FindName("grid", btnWedding); var ct0 = btnWedding.Template.FindName("textBlock2", btnWedding); var ct1 = btnWedding.FindName("textBlock2"); var ct2 = btnWedding.FindResource("textBlock2");

GridInTemplate es nulo (muestra tomada de MSDN).
Los ct # son todos nulos, por supuesto.

¿Que me estoy perdiendo aqui?


puede usar VisualTreeHelper para iterar el árbol de botones visual para obtener cualquier elemento secundario. Puede usar esta función genérica básica para obtenerlo

private static DependencyObject RecursiveVisualChildFinder<T>(DependencyObject rootObject) { var child = VisualTreeHelper.GetChild(rootObject, 0); if (child == null) return null; return child.GetType() == typeof (T) ? child : RecursiveVisualChildFinder<T>(child); }

puedes usarlo como

TextBlock textblock = RecursiveVisualChildFinder<TextBlock>(btnWedding); if(textblock.Name == "textBlock2") {// Do your stuff here }


Si ha reemplazado a OnApplyTemplate, entonces no use FindResource () o Template.FindName () ni ningún hackeo con VisualTreeHelper. Simplemente use esto. this.GetTemplateChild("textBlock2");

Las plantillas en WPF tienen un namescope auto contenido. Esto se debe a que las plantillas se vuelven a utilizar y cualquier nombre definido en una plantilla no puede permanecer único cuando varias instancias de un control crean cada instancia de su plantilla. Llame al método GetTemplateChild para devolver referencias a los objetos que provienen de la plantilla después de crear una instancia. No puede usar el método FrameworkElement.FindName para buscar elementos de plantillas porque FrameworkElement.FindName actúa en un ámbito más general, y no hay conexión entre la clase ControlTemplate y la plantilla instanciada una vez que se aplica.

Mira este enlace:

http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.gettemplatechild.aspx

Si su ejemplo es microsoft example, le sugiero que lo lea nuevamente. Es posible que hayas salteado algo.

http://msdn.microsoft.com/en-us/library/bb613586.aspx

En resumen: use GetTemplateChild () cuando cree un control personalizado, por ejemplo, OnApplyTemplate, y use Template.FindName en otras situaciones.


Su código es correcto, pero probablemente no esté en el lugar correcto ... FindName solo funcionará después de que se haya aplicado la plantilla. Normalmente, lo usa cuando anula OnApplyTemplate en un control personalizado. Como no está creando un control personalizado, puede hacerlo en el evento Cargado del botón.


El método "FrameworkElement.FindName (string name)" usa el namescope del diseño donde se usa el botón / control para resolver los nombres. En resumen, puede usar esto para encontrar niños en una cuadrícula o panel de pila en el diseño de su aplicación. Pero no puede usar el mismo para encontrar los elementos secundarios de un control que haya utilizado en el diseño de la aplicación (porque los nombres de los niños con plantillas están en un ámbito diferente)

Una forma de obtener a los niños en su situación es heredar el botón. Como no modificará ninguna otra propiedad o comportamiento del botón, el nuevo botón funcionará como uno normal. Prácticamente nunca he usado un método de este tipo para acceder a los niños con plantillas ya que nunca tuve la necesidad de usarlos fuera del alcance de la clase del control.

public class WeddingButton : Button { public override void OnApplyTemplate() { TextBlock textBlock = this.GetTemplateChild("textBlock2") as TextBlock; base.OnApplyTemplate(); } } <Page.Resources> <ControlTemplate x:Key="WeddingButtonBigTemplate" TargetType="Button"> <Grid> <Image x:Name="imgNormal" Source="../Images/Married_button2.png"/> <TextBlock x:Name="textBlock2" Style="{StaticResource RegularBlueSpecialBoldText}" LineHeight="28" LineStackingStrategy="BlockLineHeight" HorizontalAlignment="Center" Margin="10,30,10,70" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Stretch" > <Run FontSize="20" Text="The event of"></Run> <Run FontSize="28" Text="{DynamicResource strBride}"></Run> </TextBlock> </Grid> </ControlTemplate> </Page.Resources> <Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1000"> <WeddingButton x:Name="btnWedding" HorizontalAlignment="Left" Margin="10,20,0,-49" VerticalAlignment="Top" Template="{StaticResource WeddingButtonBigTemplate}" Foreground="#FF2B4072" Width="380" Click="btnClick" /> </Grid>


Pruebe el siguiente código. Esto devolverá el elemento con plantilla.

this.GetTemplateChild("ControlName");