c# wpf xaml triggers contentcontrol

c# - ¿Cómo puedo encontrar un elemento insertado por desencadenador de estilo por nombre en WPF?



xaml triggers (1)

Primero, el corazón de la pregunta: si un elemento se asigna como el contenido de un ContentControl a través de un activador de estilo, parece que no puedo encontrarlo por su nombre.

Ahora, para más detalles: tengo un panel que varía mucho en su diseño y funcionalidad en función de su contexto de datos, que es un error de un depósito de errores. Cuando ese error es nulo, es un formulario de búsqueda, cuando no es nulo, es un simple visor de las propiedades de ese error. El XAML luego se ve algo así como:

<ContentControl DataContext="..."> <ContentControl.Style> <Style TargetType="ContentControl"> <Setter Property="Content"> <Setter.Value> ... </Setter.Value> </Setter> <Style.Triggers> <DataTrigger Binding="{Binding}" Value="{x:Null}"> <Setter Property="Content"> <StackPanel> <TextBox Name="Waldo"/> <Button .../> </StackPanel> </Setter> </DataTrigger> </Style.Triggers> </Style> </ContentControl.Style> </ContentControl>

Cuando el usuario hace clic en el botón que se encuentra junto al cuadro de texto, recibo una devolución de llamada en el código que está detrás. Desde ese punto me gustaría poder acceder a varias propiedades del cuadro de texto. La pregunta es, ¿dónde está Waldo ? :)

En el código subyacente, he intentado algunas variantes de las siguientes, todas con poco éxito:

this.FindName("Waldo"); // Always returns null

He visto mucha discusión sobre este tema en lo que se refiere a las plantillas, pero no a lo relacionado con la configuración de contenido directamente con los desencadenantes. Tal vez es porque estoy violando todo tipo de mejores prácticas al hacer esto :)

¡Gracias!


Si un elemento se asigna como el Content de un ContentControl través de un activador de estilo, parece que no puedo encontrarlo por su nombre.

Si necesita acceder al Content antes de que se produzca el desencadenador, lo más probable es que no sea posible. En esta situación, lo más importante para obtener acceso después de que se produce DataTrigger.

Estoy violando todo tipo de mejores prácticas haciendo esto

Tal vez no sea la manera correcta de trabajar con el Servicio en WPF, más aún necesita acceso a contenido dinámico , que luego puede modificarse. Pero, en cualquier caso, hay dos formas de trabajar con el control electrónico: es como ahora y en el estilo MVVM. El estilo MVVM es el más adecuado para aplicaciones grandes y menos complejas con lógica comercial diferente. Si en su caso es fácil de aplicar, en esta situación, no veo nada de malo en eso. Además de hacer un proyecto en el estilo MVVM necesita desde el principio, combinar el método convencional y el método correcto no es una buena manera.

Creé un pequeño ejemplo para demostrar los controles de acceso para una situación dada. Hay una propiedad que corresponde al tipo de Contenido, el valor predeterminado es Init . Si asigna nulo para esta propiedad, se carga el contenido dinámico.

Así es como tengo acceso a TextBox :

private void GetAccessToTextBox_Click(object sender, RoutedEventArgs e) { TextBox MyTextBox = null; StackPanel panel = MainContentControl.Content as StackPanel; foreach (object child in panel.Children) { if (child is TextBox) { MyTextBox = child as TextBox; } } if (MyTextBox != null) { MyTextBox.Background = Brushes.Gainsboro; MyTextBox.Height = 100; MyTextBox.Text = "Got access to me!"; } }

A continuación se muestra un ejemplo completo:

XAML

<Window x:Class="AccessToElementInContentControl.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:this="clr-namespace:AccessToElementInContentControl" WindowStartupLocation="CenterScreen" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <this:TestData /> </Window.DataContext> <Window.Resources> <Style TargetType="{x:Type ContentControl}"> <Setter Property="Content"> <Setter.Value> <Label Content="InitContent" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Setter.Value> </Setter> <Style.Triggers> <DataTrigger Binding="{Binding Path=TypeContent}" Value="{x:Null}"> <Setter Property="Content"> <Setter.Value> <StackPanel Name="NullStackPanel"> <TextBox Name="Waldo" Text="DynamicText" /> <Button Width="100" Height="30" Content="DynamicButton" /> </StackPanel> </Setter.Value> </Setter> </DataTrigger> </Style.Triggers> </Style> </Window.Resources> <Grid> <ContentControl Name="MainContentControl" /> <Button Name="SetContentType" Width="100" Height="30" HorizontalAlignment="Left" Content="SetContentType" Click="SetContentType_Click" /> <Button Name="GetAccessToButton" Width="110" Height="30" HorizontalAlignment="Right" Content="GetAccessToTextBox" Click="GetAccessToTextBox_Click" /> </Grid> </Window>

Code-behind

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void SetContentType_Click(object sender, RoutedEventArgs e) { TestData test = this.DataContext as TestData; test.TypeContent = null; } private void GetAccessToTextBox_Click(object sender, RoutedEventArgs e) { TextBox MyTextBox = null; StackPanel panel = MainContentControl.Content as StackPanel; foreach (object child in panel.Children) { if (child is TextBox) { MyTextBox = child as TextBox; } } if (MyTextBox != null) { MyTextBox.Background = Brushes.Gainsboro; MyTextBox.Height = 100; MyTextBox.Text = "Got access to me!"; } } } public class TestData : NotificationObject { private string _typeContent = "Init"; public string TypeContent { get { return _typeContent; } set { _typeContent = value; NotifyPropertyChanged("TypeContent"); } } } public class NotificationObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }