form - wpf windows resources
¿Por qué las aplicaciones WPF tienen un aspecto diferente entre Windows 7 y Windows 8 y esto puede solucionarse? (4)
Estoy realmente sorprendido de que esta pregunta no parece haber sido formulada todavía ... si es así, pero no pude encontrarla, me disculpo.
Ok, entonces mi computadora de trabajo acaba de actualizarse de Windows 7 a Windows 8. Para mi horror absoluto, mi aplicación WPF se ve diferente de varias maneras ... por diferentes, quiero decir, peor, más feos, los controles no están alineados correctamente, etc. Aquí hay un ejemplo:
Windows 7:
Windows 8:
Problemas de Windows 8 (solo de esta imagen):
- Barra de título incorrecta que incluye botones (Minimizar, Cerrar, etc.)
- Tamaño incorrecto Fuente en la barra de título
- FontWeight incorrecto en los encabezados (configuración de Windows 7 SemiBold = configuración de Windows 8 Bold)
- Icono (o texto) desalineado en la barra de título
- El icono en la barra de título es muy borroso.
- Los ajustes de relleno y / o margen incorrectos espacian los elementos a la izquierda
- Relleno incorrecto y / o configuración de Margen reduciendo las Alturas de Textbox a la derecha
- El color de selección predeterminado ''Oculto'' en los elementos de la izquierda ya no está oculto
- Volver al frente Checkbox tick
- Las imágenes en algunos botones son muy borrosas
Así que mi pregunta es esta:
¿Por qué las aplicaciones WPF tienen un aspecto diferente entre Windows 7 y Windows 8 y esto puede solucionarse?
Para aclarar esto, no busco una lista de diferencias entre WPF en los dos sistemas operativos. Tampoco estoy después de las correcciones para los puntos individuales mencionados anteriormente. Me gustaría que alguien explique por qué estas IU se ven diferentes, por ejemplo. Lo que está causando estas diferencias. También he escuchado hablar de algunas configuraciones del sistema en WPF que me permitirían hacer que la PC renderice la aplicación como si estuviera en Windows 7 , pero no sé cuán verídica fue esa.
ACTUALIZACIÓN >>>
Como @ AndrasSebö señaló amablemente, ¿hay una pregunta de StackOverflow llamada tema de Windows 7 para WPF? , que soluciona un problema similar para Windows XP. Desafortunadamente, no parece tener ningún efecto en Windows 8. ¿Hay algún usuario de Microsoft que sepa qué diferencias se implementaron para causar este problema? O alguien?
ACTUALIZACIÓN 2 >>>
Bien, después de algunas pruebas más, estoy empezando a pensar que este problema no está relacionado con el tema de Windows. Usando el código provisto en la respuesta de @Gusdor, intenté cambiar el tema a Aero
y no había una diferencia visible ... eso me hizo pensar. Luego lo cambié a Luna
para probar ese código y funcionó.
Por "trabajado", quiero decir que el tema de Windows cambió, pero la interfaz de usuario controla, o más exactamente, el Padding
y el Margin
incorrectos se mantuvieron. Luego intenté cambiar el tema a Luna
usando el método XAML mencionado por @ AndrasSebö y sucedió lo mismo ... los ScrollBar
veían diferentes, así que pude ver que el tema había cambiado, pero el problema seguía.
Así que ahora estoy pensando que esto podría tener algo que ver con el hecho de que esta es una computadora nueva en la que estoy trabajando ... ¿podría haber alguna DLL o configuración que necesito instalar? Realmente estoy adivinando aquí: tengo todo el .NET Framework instalado en la versión 4.5.1, ya que estoy en Windows 8.1.
Esta es una pesadilla absoluta, ya que no tengo tiempo para arreglar todas las vistas en esta gran aplicación. Por favor ayuda si puedes.
El problema (como se describe en otras respuestas) es que WPF elige un tema predeterminado determinado por la versión del sistema operativo.
Es necesario anular este comportamiento. ESTE ARTÍCULO describe cómo:
WPF viene con algunos conjuntos de temas, uno para cada tema de Windows (Luna, Royale y Aero y el tema de respaldo, clásico). Por lo general, el tema se carga de acuerdo con el tema de su sistema actual, pero si desea crear un aspecto coherente para su aplicación, es posible que desee forzar la carga de una específica.
Para lograr eso, simplemente agregue el siguiente código en su evento de inicio de aplicación (este ejemplo muestra cómo usar el tema Aero):
Uri uri = new Uri(“PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component//themes/aero.normalcolor.xaml”, UriKind.Relative);
Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);
Es importante especificar la versión y el token de clave pública. De lo contrario, tendrá que copiar el conjunto del tema en la carpeta de su ejecutable. La razón por la que lo agrego a la colección de diccionarios combinados es que no quiero perder otros recursos que agregué al archivo App.xaml.
Ok, desafortunadamente, no hubo una solución rápida para este problema. Si se encuentra en una situación similar y las respuestas proporcionadas aquí tampoco funcionan, entonces aquí hay un resumen de los cambios que tuve que hacer manualmente para que la interfaz de usuario en Windows 8 parezca lo mismo que la interfaz de usuario en Windows. 7.
TextBox
: necesario para agregar Padding
al Style
predeterminado:
<Setter Property="Padding" Value="1.5,2" />
ListBoxItem
: se necesita para proporcionar una nueva ListBoxItem
ControlTemplate
para ocultar la selección y el mouse sobre los colores de fondo:
<Style x:Key="DefaultListBoxItem" TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="2,0,1,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Local" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" Duration="0" To=".55" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/>
<Rectangle x:Name="FocusVisualElement" Fill="{x:Null}" Stroke="{x:Null}" StrokeThickness="0" Visibility="Collapsed" RadiusX="1" RadiusY="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ComboBoxItem
: se necesita para proporcionar una nueva ControlTemplate
para cambiar la selección y el mouse sobre los colores de fondo:
<Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border x:Name="Border" Padding="2" SnapsToDevicePixels="true" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FF47484C" /> <!-- Background mouse over colour -->
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="White" /> <!-- Foreground mouse over colour -->
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FF47484C" /> <!-- Background selection colour -->
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="White" /> <!-- Foreground selection colour -->
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CheckBox
: se necesita proporcionar una nueva ControlTemplate
para evitar que la marca aparezca de nuevo al frente cuando Bullet
está a la derecha del Content
(gracias a la respuesta de Fredrik a la ControlTemplate predeterminada para la pregunta de CheckBox aquí en :
<SolidColorBrush x:Key="CheckBoxFillNormal" Color="#F4F4F4" />
<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F" />
<Style x:Key="EmptyCheckBoxFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="1" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CheckRadioFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="14,0,0,0" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{StaticResource CheckBoxFillNormal}"/>
<Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator Background="Transparent" SnapsToDevicePixels="true">
<BulletDecorator.Bullet>
<Aero:BulletChrome BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" IsChecked="{TemplateBinding IsChecked}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"/>
</BulletDecorator.Bullet>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
<Setter Property="Padding" Value="4,0,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Para eliminar la horrenda barra de título y mostrar el Windows 8 predeterminado: necesario para actualizar a .NET 4.5 y utilizar la biblioteca de espacio de nombres System.Windows.Controls.Ribbon
incluida en lugar de la dll ''Microsoft Ribbon for WPF'' (RibbonControlsLibrary) utilizada anteriormente .
Desafortunadamente, nunca descubrí cómo reproducir la configuración SemiBold
de la propiedad FontWeight
en Windows 8. Si alguien sabe cómo hacerlo, hágamelo saber.
En general, el cambio a Windows 8 ha sido una experiencia dolorosa y preocupante. Espero que esta información ayude a otros de una manera un poco menos dolorosa.
Si usa WPF sin un estilo personalizado (explícito), usará el estilo aero de Windows 7 estándar. En el caso de Windows 8 es diferente (aero2).
Si desea asegurarse, su aplicación aparece igual en windows7 y en windows8, así que le recomiendo que cree un estilo personalizado en el que defina márgenes, rellenos, fuentes, etc.
Su problema puede estar relacionado con this
Actualmente hay un error en la biblioteca de cintas de WPF, que hace que el tema de Windows 8 no se aplique si se está utilizando una ventana de cinta.
Además, Windows 7 y 8 utilizan simplemente diferentes estilos para sus controles, como los cuadros de texto. Al desarrollar para múltiples plataformas, ya sea solo Windows, debe tener en cuenta que los tamaños, márgenes y rellenos cambian. En lugar de valores absolutos, debe dejar que los controles determinen su necesidad de espacio, evitando establecer alturas o anchos explícitos por completo.