c# - usando - Verificación del tiempo de diseño de los argumentos de extensión de marcado en el diseñador WPF
matematicas para tercer grado de primaria (2)
No, desafortunadamente, mi comprensión del problema es esto,
La resolución del tiempo de diseño parece funcionar en WPF debido a las propiedades de dependencia. Dado que MarkupExtension
no se deriva del objeto de dependencia, su extensión nunca se evalúa en el momento del diseño. En cuanto al clima, esto fue un descuido o intencional es discutible.
Puede haber otra forma de resolver esto, aunque sería ligeramente diferente. Crea una nueva propiedad adjunta llamada MergeStyles. En esa propiedad puede especificar los nombres de estilo que desea combinar y aplicar. Cuando se cambia el valor, simplemente actualice el estilo del adjunto con su código anterior. Puede usar la posición en la que viene cada estilo que se fusionará para determinar la jerarquía.
No es exactamente lo que quieres pero puede llegar hasta la mitad del camino. Sin embargo, el resultado de esto es que puedes unirte a él.
He escrito una extensión de marcado para WPF que me permite hacer
<!-- Generic Styles -->
<Style x:Key="bold" TargetType="Label">
<Setter Property="FontWeight" Value="ExtraBold" />
</Style>
<Style x:Key="italic" TargetType="Label">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<Style x:Key="gridHeader" TargetType="Label"
BasedOn="{WPF:CombiStyle bold italic }" >
Es una extensión muy útil y funciona muy bien en tiempo de ejecución. Sin embargo, en el momento del diseño no puedo ver los estilos aplicados o, si escribo mal el texto en negrita y la cursiva, es posible que no se encuentren como recursos estáticos.
¿Qué hacks puedo hacer para que esto funcione?
El código fuente de la extensión es
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Markup;
namespace MarkupExtensions
{
[MarkupExtensionReturnType(typeof(Style))]
public class CombiStyleExtension : MarkupExtension
{
private string[] MergeStyleProviders { get; set; }
public CombiStyleExtension(string s0)
{
MergeStyleProviders = s0.Split(new[]{'' ''});
}
public override object ProvideValue(IServiceProvider
serviceProvider)
{
return MergeStyleProviders
.Select(x => StringToStyle(serviceProvider, x))
.Aggregate(new Style(), RecursivelyMergeStyles);
}
private static Style StringToStyle(IServiceProvider serviceProvider, string x)
{
var style = new StaticResourceExtension() { ResourceKey = x }.ProvideValue(serviceProvider) as Style;
if (style==null)
{
throw new ArgumentException("Argument could not be converted to a style");
}
return style;
}
private static Style RecursivelyMergeStyles(Style accumulator,
Style next)
{
if (next.BasedOn != null)
{
RecursivelyMergeStyles(accumulator, next.BasedOn);
}
MergeStyle(accumulator, next);
return accumulator;
}
private static void MergeStyle(Style targetStyle, Style sourceStyle)
{
targetStyle.TargetType = sourceStyle.TargetType;
// Merge the Setters...
foreach (var setter in sourceStyle.Setters)
targetStyle.Setters.Add(setter);
// Merge the Triggers...
foreach (var trigger in sourceStyle.Triggers)
targetStyle.Triggers.Add(trigger);
}
}
}
Actualización: se agregaron capturas de pantalla para VS2012 (funciona bien) y Blend para VS2012 (funciona parcialmente: los estilos base en los estilos BasedOn no se seleccionan correctamente por algún motivo).
También lo verifiqué en Vista previa de VS2013 y Mezcla para Vista previa de VS2013 - allí funciona parcialmente y exactamente igual que en Mezcla para VS2012 . Espero que solucionen esto en el lanzamiento.
El problema es que el diseñador de Visual Studio tiene una gran simpatía cuando el objeto que intenta describir en XAML tiene un constructor público predeterminado que utiliza para instanciar la instancia en tiempo de diseño de ese objeto.
He actualizado un poco su clase CombiStyleExtension.cs para tener esto en cuenta y al diseñador de Visual Studio 2010 le gusta ahora. Sin embargo, el diseñador de Blend 4 todavía no lo hace, lo siento.
Echar un vistazo:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
namespace WpfApplication7
{
[MarkupExtensionReturnType(typeof(Style))]
public class CombiStyleExtension : MarkupExtension
{
/// <summary>
/// Set space-separated style names i.e. "size16 grey verdana".
/// </summary>
public string Names { private get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Names.Split(new[] { '' '' })
.Select(x => Application.Current.TryFindResource(x)
as Style)
.Aggregate(new Style(), RecursivelyMergeStyles);
}
private static Style RecursivelyMergeStyles(Style accumulator,
Style next)
{
if(accumulator == null || next == null)
return accumulator;
if(next.BasedOn != null)
RecursivelyMergeStyles(accumulator, next.BasedOn);
MergeStyle(accumulator, next);
return accumulator;
}
private static void MergeStyle(Style targetStyle, Style sourceStyle)
{
if(targetStyle == null || sourceStyle == null)
{
return;
}
targetStyle.TargetType = sourceStyle.TargetType;
// Merge the Setters...
foreach(var setter in sourceStyle.Setters)
targetStyle.Setters.Add(setter);
// Merge the Triggers...
foreach(var trigger in sourceStyle.Triggers)
targetStyle.Triggers.Add(trigger);
}
}
}
El uso de esta extensión de marcado también cambió un poco. Cómo fue:
BasedOn="{WPF:CombiStyle bold italic }"
y como ahora
BasedOn="{WPF:CombiStyle Names=''bold italic''}"
Y solo para ahorrarle un poco de tiempo aquí es un poco de xaml para copiar, pegar, ejecutar y ver:
MainWindow.xaml :
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPF="clr-namespace:WpfApplication7"
Title="MainWindow" Height="350" Width="569">
<Window.Resources>
<!-- Did not managed to make the type-level style work -->
<!-- from app.xaml, so put it here. Just in case. -->
<Style TargetType="{x:Type Label}"
BasedOn="{WPF:CombiStyle Names=''size16 grey verdana''}" />
</Window.Resources>
<StackPanel>
<Label Content="Type-level: size16 + grey + verdana" />
<Label Content="''h1'': size24 + royalBlue" Style="{DynamicResource h1}" />
<Label Content="''warning'': size24 + yellow + bold + shadow"
Style="{DynamicResource warning}" />
<Label Content="Inline: size12 + italic"
Style="{WPF:CombiStyle Names=''size12 italic''}" />
<Label Content="Inline: size16 + bold + italic + red"
Style="{WPF:CombiStyle Names=''size16 bold italic red''}" />
<Label Content="Inline: size24 + green"
Style="{WPF:CombiStyle Names=''size24 green''}" />
</StackPanel>
</Window>
App.xaml :
<Application x:Class="WpfApplication7.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPF="clr-namespace:WpfApplication7"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!-- Sizes -->
<Style x:Key="size12" TargetType="Label">
<Setter Property="FontSize" Value="12" />
</Style>
<Style x:Key="size16" TargetType="Label">
<Setter Property="FontSize" Value="16" />
</Style>
<Style x:Key="size24" TargetType="Label">
<Setter Property="FontSize" Value="24" />
</Style>
<!-- Bold/Italic -->
<Style x:Key="bold" TargetType="Label">
<Setter Property="FontWeight" Value="ExtraBold" />
</Style>
<Style x:Key="italic" TargetType="Label">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<!-- Colors -->
<Style x:Key="grey" TargetType="Label">
<Setter Property="Foreground" Value="#333333" />
</Style>
<Style x:Key="royalBlue" TargetType="Label">
<Setter Property="Foreground" Value="RoyalBlue" />
</Style>
<Style x:Key="green" TargetType="Label">
<Setter Property="Foreground" Value="Green" />
</Style>
<Style x:Key="yellow" TargetType="Label">
<Setter Property="Foreground" Value="Yellow" />
</Style>
<Style x:Key="red" TargetType="Label">
<Setter Property="Foreground" Value="#D00000" />
</Style>
<!-- Fonts -->
<Style x:Key="verdana" TargetType="Label">
<Setter Property="FontFamily" Value="Verdana" />
</Style>
<!-- Effects -->
<Style x:Key="shadow" TargetType="Label">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" />
</Setter.Value>
</Setter>
</Style>
<!-- Predefined Combinations -->
<Style x:Key="h1" TargetType="{x:Type Label}"
BasedOn="{WPF:CombiStyle Names=''size24 royalBlue''}" />
<Style x:Key="warning" TargetType="{x:Type Label}"
BasedOn="{WPF:CombiStyle Names=''size24 yellow bold shadow''}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="Yellow" />
</Style>
</Application.Resources>
</Application>
Disfrutar;)