example - textbox wpf
Estilos implícitos en Application.Resources vs Window.Resources? (4)
Este es realmente el único manejo especial agregado a WPF y fue hecho por diseño. El código que lo implementa se puede encontrar en FrameworkElement
, en el método FindImplicitStyleResource
, que efectivamente hace:
internal static object FindImplicitStyleResource(FrameworkElement fe, object resourceKey, out object source)
{
// ...
DependencyObject boundaryElement = null;
if (!(fe is Control))
boundaryElement = fe.TemplatedParent;
// ...
}
Entonces, la regla de oro es que los Estilos implícitos siempre se aplican a los controles (es decir, deriva del Control
). Asumiendo que se puede encontrar el Estilo implícito.
Para los elementos utilizados en una plantilla de Control
que no se derivan del Control
, como TextBlock
, la búsqueda de estilo implícita no cruza su elemento primario con plantilla. En su caso anterior, este sería el ComboBox
.
Creo que esto se hizo para que los Estilos implícitos que no son de aplicación para TextBlock no se aplicaran inadvertidamente a los elementos de TextBlock
utilizados en las plantillas de control, que el desarrollador puede haber sabido o no. Los Estilos implícitos solo se aplicarían a los TextBlocks realmente creados por el desarrollador en su propio XAML.
La aplicación de Estilos implícitos aún permitiría un estilo global, como aumentar el tamaño de la fuente. Pero probablemente haya causado más confusión de lo que vale.
No hay una buena respuesta para decir cuándo usar uno frente a otro, ya que cada uno tiene su función. Obviamente, si no quiere afectar cada TextBlock
en su aplicación, no debe poner el estilo en los recursos de la aplicación.
Pero tenga en cuenta que esto afecta a cualquier elemento que no sea Control
, como los elementos Shape
.
Estaba viendo esta pregunta y me di cuenta de que colocaba un estilo de TextBlock
implícito en Application.Resources
aplica ese estilo a todos los TextBlocks, incluso a los que están dentro de otros controles como Buttons
, ComboBoxes
, etc.
<Application.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</Application.Resources>
Colocar el estilo implícito en Window.Resources
no cruza los límites de la plantilla , por lo que cosas como Buttons
y ComboBoxes
mantienen su texto negro predeterminado.
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</Window.Resources>
Además, agregar el estilo predeterminado en Application.Resources
hace para que no pueda sobreescribir ese estilo con otro estilo implícito.
<!-- Doesn''t work if implicit style with same property is in Application.Resources -->
<ComboBox.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red" />
</Style>
</ComboBox.Resources>
Mis preguntas son:
- ¿Por qué es esto?
- ¿Hay otras diferencias entre
Application.Resources
yWindows.Resources
? ¿Cuándo debería usar uno sobre el otro?
Entiendo que
Application.Resources
aplica a toda la aplicación, mientras queWindow.Resources
aplica solo a la ventana, sin embargo, quiero saber por qué los estilos enApplication
se tratan de manera diferente a los estilos enWindow
La diferencia radica en el alcance de los estilos:
- cuando se coloca en Application.Resources, se aplicará un estilo a todos los controles en la aplicación
- cuando se coloca dentro de Windows.Resources, se aplicará un estilo a todos los controles en la ventana
la diferencia es bastante sutil allí, pero lo que significa es que sea cual sea el control del que estamos hablando (incluido uno que está en la plantilla de otro control) obtendrá el estilo de la aplicación. Recursos. pero solo los controles directamente hijos de la ventana obtendrán el estilo de la ventana. Recursos. Un control dentro de la plantilla del control no tendrá el estilo definido en Window.Resources ya que no está directamente en la ventana, mientras que tendrá el estilo definido en Application.Resources ya que está en la aplicación.
en cuanto a su segundo punto, tiene que ver con la precedencia de propiedad de dependencia, creo:
Muy simple como simple
Si desea que los recursos se compartan entre la aplicación ENTERA, usaría Application.Resources
Si quiere que los recursos se compartan entre la ventana ENTERA, usaría Window.Resources
Si desea que los recursos se compartan entre un único control que usaría (sea cual sea el control). Recursos
Supongamos que tiene varias ventanas pero solo quiere un estilo predeterminado en una, pero no en la otra, entonces debería usar Windoe.Resources
Rachel, no creo que haya nada especial para "Styles". Además, no hay un problema de "cruzar límites de plantilla". La razón de esto es diferente y va a los diferentes "Árboles" en una aplicación de WPF. Con tu pregunta, te imagino que estás imaginando un mundo con la siguiente jerarquía:
- Aplicación => Ventana => Control => Elementos dentro del control
No existe tal jerarquía. Hay árboles diferentes en una aplicación de WPF, los más famosos son el Árbol lógico y el Árbol visual, pero hay más (el árbol de eventos de enrutamiento y también el árbol de búsqueda de recursos, con una semántica ligeramente diferente).
Supongamos el siguiente XAML:
<Window x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="btn" Click="click">Click Me</Button>
</Grid>
</Window>
Para este XAML, el árbol lógico se verá así:
- Ventana => Cuadrícula => Botón => Cadena
El bloque de texto dentro del botón no es parte del árbol lógico (aunque es parte del VisualTree).
Buscar recursos pasa por LogicalTree, con una diferencia. Después de que llegue al objeto superior, el algoritmo de recursos de búsqueda buscará en el diccionario de recursos de la aplicación , y luego en el elemento dietario del recurso del tema, y luego en el diccionario de recursos del sistema en este orden.
Ver los siguientes artículos:
- Acerca de los árboles: http://msdn.microsoft.com/en-us/library/ms753391.aspx
- Acerca de la búsqueda de recursos: http://msdn.microsoft.com/en-us/library/ms750613.aspx#staticdynamic , y busque la sección "Comportamiento de búsqueda de recursos dinámicos"
Finalmente, para probar mi punto, agregue el siguiente recurso a la aplicación XAML:
<Application x:Class="SO.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
StartupUri="MainWindow.xaml">
<Application.Resources>
<clr:String x:Key="MyResource">Hello Application Resource</clr:String>
</Application.Resources>
</Application>
y el siguiente código detrás:
private void click(object sender, RoutedEventArgs e)
{
// Logical Children of btn
Debug.WriteLine("Children of btn:");
foreach( var x in LogicalTreeHelper.GetChildren(btn) ) {
Debug.WriteLine("{0} : {1}", x, x.GetType());
}
// Walk the visual tree
Debug.WriteLine("The Visual Tree:");
WalkVisual(0, this);
// Find the textblock within the button
DependencyObject p = btn;
while (p.GetType() != typeof(TextBlock))
p = VisualTreeHelper.GetChild(p, 0);
TextBlock tb = p as TextBlock;
// Now climp the textblock through the logical tree
while (p != null)
{
Debug.WriteLine("{0}", p.GetType());
p = LogicalTreeHelper.GetParent(p);
}
// Find a resource for the textbox
string s = tb.FindResource("MyResource") as string;
Debug.WriteLine("MyResource Content: {0}", s);
}
private void WalkVisual(int indent, DependencyObject p)
{
string fmt = string.Format("{{0,{0}}}{{1}}", indent * 4);
Debug.WriteLine(fmt, "", p.GetType());
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(p); ++i)
{
WalkVisual(indent+1,VisualTreeHelper.GetChild(p, i));
}
}
Entonces ... una vez que entiendes la primera pregunta (''¿por qué es eso?''), Las otras preguntas se desmoronan. La diferencia entre los recursos de la aplicación y los recursos de la ventana es que los recursos de la aplicación pueden ser originados por cualquier DependencyObject en su aplicación, incluidos aquellos definidos en otros ensambles. Lo usarás cuando esto sea lo que quieres lograr :-)
tú