为画笔创建 WPF ValueConverter
关于 Nerd Plus今天Art博客,有一篇关于为箭头创建WPF资源的帖子,作者经常使用。 我有一个带有“后退”和“前进”按钮的副项目,因此我认为向左和向右箭头在这些按钮上效果很好。
我将 LeftArrow
和 RightArrow
几何图形添加到应用程序的资源中,然后将它们用作按钮的内容:
<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>
这有效,除了箭头被绘制为黑色,无论按钮是否启用。 因此,我创建了一个 ValueConverter
来从 bool
转换为 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();
}
}
我意识到我应该使用系统颜色而不是硬编码黑色和灰色,但我只是想让它工作,首先。)
我修改了 Path
的 Fill
属性以使用我的转换器(我在应用程序的资源中创建的转换器) ):
<Path Data="{StaticResource LeftArrow}" Width="10" Height="8"
Stretch="Fill"
Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled, Converter={StaticResource EnabledColorConverter}}"/>
不幸的是,这不起作用,我不知道为什么。 当我运行它时,箭头根本没有被绘制。 我检查了 Visual Studio 中的“输出”窗口,没有显示绑定错误。 我还根据是否应启用按钮来验证 bool
是转换器中的正确值。
如果我将 Path
更改回 TextBlock
(并以与 Path.Fill
相同的方式绑定其 Foreground
属性>),文本始终以黑色绘制。
难道我做错了什么? 为什么我的转换器返回的 Brush
不用于渲染按钮中的 Path
?
On the Nerd Plus Art blog today, there was a post about creating WPF Resources for arrows, which the author uses frequently. I have a side project that has Back and Forward buttons, so I thought that the Left and Right arrows would work great on those buttons.
I added the LeftArrow
and RightArrow
Geometries to my application's resources, and then used them as the content of the buttons:
<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>
That worked, except that the arrows were drawn in black regardless of whether the button was enabled or not. So, I created a ValueConverter
to go from a bool
to a 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();
}
}
(I realize that I should probably use system colors instead of hard coded black and gray, but I just wanted to get this working, first.)
I modified the Fill
property of the Path
to use my converter (which I created within the application's resources):
<Path Data="{StaticResource LeftArrow}" Width="10" Height="8"
Stretch="Fill"
Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled, Converter={StaticResource EnabledColorConverter}}"/>
Unfortunately, this doesn't work, and I'm not sure why. When I run it, the arrow isn't drawn at all. I checked the Output window in Visual Studio, and no binding errors were displayed. I also verified that the bool
is the right value in the converter, based on the whether the button should be enabled or not.
If I change the Path
back to a TextBlock
(and bind its Foreground
property in the same manner as Path.Fill
), the text is always drawn in black.
Am I doing something wrong? Why is the Brush
returned by my converter not used to render the Path
in the button?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于这种 UI 状态更新,请尝试使用触发器; 它可以让你免去编写值转换器的麻烦,而且编写起来要短得多。
尝试以下操作:
然后,分别为左箭头和右箭头设置 LeftArrowStyle 和 RightArrowStyle 的默认填充。 如果您将其设置在路径本身上,则该值将优先并覆盖样式或其触发器可能执行的任何操作。 基本样式 ArrowStyle 包含绑定到父按钮的 DataTrigger - 只要 IsEnabled 为 false,它就会触发,并将路径的填充更改为灰色。
For this kind of UI state updates, try using triggers instead; it'll save you from writing a value converter, and it's a lot shorter to write.
Try this:
Then, you set your default fill in LeftArrowStyle and RightArrowStyle, for the left and right arrows, respectively. If you set it on the Path itself, then that value would take precedence and override anything a style or its trigger may do. The base style, ArrowStyle, contains a DataTrigger bound to the parent button - it fires whenever IsEnabled is false, and changes the Path's Fill to Gray.
为什么不将路径的填充绑定到按钮的前景呢?
Why no just bind the Fill of your Path to the Foreground of the Button?
你的代码基本上可以工作。 我认为您的静态资源可能是错误的,因为您没有指定从哪里获取转换器。
您可能需要
然后将您的绑定指定为:
Your code essentially works. I think your static resource may be wrong as your not specifying where this is getting the converter from.
You probably need
and then specify your binding as: