La creación de un WPF ValueConverter para un cepillo
-
09-09-2019 - |
Pregunta
En la Nerd Plus Arte hoy blog, hubo un post acerca de la creación de recursos WPF para las flechas, que el autor utiliza con frecuencia. Tengo un proyecto paralelo que tiene los botones Atrás y Adelante, así que pensé que la flechas izquierda y derecha funcionarían muy bien en esos botones.
He añadido las geometrías LeftArrow
y RightArrow
a los recursos de mi aplicación, y luego los utiliza como el contenido de los botones:
<Application x:Class="Notes.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<Geometry x:Key="RightArrow">M0,0 L1,0.5 0,1Z</Geometry>
<Geometry x:Key="LeftArrow">M0,0.5 L1,1 1,0Z</Geometry>
</Application.Resources>
</Application>
<Button x:Name="BackButton"
Padding="5,5,5,5"
Command="{x:Static n:Commands.GoBackCommand}">
<Path Data="{StaticResource LeftArrow}" Width="10" Height="8"
Stretch="Fill" Fill="Black"/>
</Button>
<Button x:Name="ForwardButton"
Padding="5,5,5,5"
Command="{x:Static n:Commands.GoForwardCommand}">
<Path Data="{StaticResource RightArrow}" Width="10" Height="8"
Stretch="Fill" Fill="Red" />
</Button>
Eso funcionó, excepto que las flechas se dibujan en negro, independientemente de si se ha activado el botón o no. Por lo tanto, he creado un ValueConverter
pasar de una bool
a un Brush
:
class EnabledColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
bool b = (bool)value;
return b ? Brushes.Black : Brushes.Gray;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
(me di cuenta de que probablemente debería utilizar los colores del sistema en vez del disco codificado en negro y gris, pero yo sólo quería conseguir este trabajo, en primer lugar.)
He modificado la propiedad Fill
del Path
usar mi convertidor (que he creado dentro de los recursos de la aplicación):
<Path Data="{StaticResource LeftArrow}" Width="10" Height="8"
Stretch="Fill"
Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled, Converter={StaticResource EnabledColorConverter}}"/>
Por desgracia, esto no funciona, y no estoy seguro de por qué. Cuando lo ejecuto, la flecha no se dibuja en absoluto. Revisé la ventana Resultados de Visual Studio, y se exhibieron ningún error vinculantes. También pude comprobar que el bool
es el valor justo en el convertidor, en base a la si el botón se debe habilitar o no.
Si cambio la Path
de nuevo a un TextBlock
(y unirse a su propiedad Foreground
de la misma manera como Path.Fill
), el texto siempre se dibuja en negro.
¿Estoy haciendo algo mal? ¿Por qué la Brush
vuelto por mi convertidor no sirve para hacer la Path
en el botón?
Solución
¿Por qué no acaba de obligar a la Preparación de su camino hacia el primer plano del botón?
<Button x:Name="BackButton"
Padding="5,5,5,5"
Command="{x:Static n:Commands.GoBackCommand}">
<Path Data="{StaticResource LeftArrow}" Width="10" Height="8"
Stretch="Fill" Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=Foreground"/>
</Button>
Otros consejos
Para este tipo de cambios de estado de interfaz de usuario, intente utilizar disparadores en su lugar; que le ahorrará a partir de escritura de un convertidor de valores, y es mucho más corto para escribir.
Prueba esto:
<Application x:Class="Notes.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<Geometry x:Key="RightArrow">M0,0 L1,0.5 0,1Z</Geometry>
<Geometry x:Key="LeftArrow">M0,0.5 L1,1 1,0Z</Geometry>
<!-- Base Arrow Style, with a trigger to toggle it Gray when its parent button is disabled -->
<Style x:Key="ArrowStyle" TargetType="Path">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="8"/>
<Setter Property="Stretch" Value="Fill"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled}" Value="False">
<Setter Property="Fill" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
<!-- Left Arrow Style, with the Left Arrow fill and data -->
<Style x:Key="LeftArrowStyle" BasedOn="{StaticResource ArrowStyle}" TargetType="Path">
<Setter Property="Fill" Value="Black"/>
<Setter Property="Data" Value="{StaticResource LeftArrow}"/>
</Style>
<!-- Right Arrow Style, with the Right Arrow fill and data -->
<Style x:Key="RightArrowStyle" BasedOn="{StaticResource ArrowStyle}" TargetType="Path">
<Setter Property="Fill" Value="Red"/>
<Setter Property="Data" Value="{StaticResource RightArrow}"/>
</Style>
</Application.Resources>
<Button x:Name="BackButton" Padding="5,5,5,5" IsEnabled="False">
<Path Style="{StaticResource LeftArrowStyle}"/>
</Button>
<Button x:Name="ForwardButton" Padding="5,5,5,5">
<Path Style="{StaticResource RightArrowStyle}"/>
</Button>
</Application>
A continuación, se establece su defecto rellene LeftArrowStyle y RightArrowStyle, por las flechas izquierda y derecha, respectivamente. Si se establece en el Sendero mismo, entonces ese valor tendría preferencia y anular cualquier cosa que un estilo o su disparador puede hacer. El estilo de base, ArrowStyle, contiene una DataTrigger unido al botón de padres -. Que se activa siempre IsEnabled es falsa, y cambia el relleno del Camino a Gray
Su código funciona esencialmente. Creo que su recurso estático puede ser errónea como su no especifica donde esto se está poniendo el convertidor de.
Es probable que tenga
<Window.Resources>
<conv:EnabledColorConverter x:Key="brushConv" />
</Window.Resources>
y, a continuación, especifique su unión como:
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled, Converter={StaticResource brushConv}}