如何使用 ItemContainerStyle 设置 MenuItem 的图标
我按照此处将 MenuItem
绑定到数据对象的示例进行操作。
<Menu Grid.Row="0" KeyboardNavigation.TabNavigation="Cycle"
ItemsSource="{Binding Path=MenuCommands}">
<Menu.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Header" Value="{Binding Path=DisplayName}"/>
<Setter Property="MenuItem.ItemsSource" Value="{Binding Path=Commands}"/>
<Setter Property="MenuItem.Command" Value="{Binding Path=Command}"/>
<Setter Property="MenuItem.Icon" Value="{Binding Path=Icon}"/>
</Style>
</Menu.ItemContainerStyle>
</Menu>
除了 MenuItem
的图标显示为字符串 System.Drawing.Bitmap
之外,一切都运行顺利。所讨论的位图由数据对象从已编译的资源返回。
internal static System.Drawing.Bitmap folder_page
{
get
{
object obj = ResourceManager.GetObject("folder_page", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
我做错了什么?
I'm following the example here of binding a MenuItem
to a data object.
<Menu Grid.Row="0" KeyboardNavigation.TabNavigation="Cycle"
ItemsSource="{Binding Path=MenuCommands}">
<Menu.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Header" Value="{Binding Path=DisplayName}"/>
<Setter Property="MenuItem.ItemsSource" Value="{Binding Path=Commands}"/>
<Setter Property="MenuItem.Command" Value="{Binding Path=Command}"/>
<Setter Property="MenuItem.Icon" Value="{Binding Path=Icon}"/>
</Style>
</Menu.ItemContainerStyle>
</Menu>
It all works swimmingly except the MenuItem
's icon shows up as the string System.Drawing.Bitmap
. The bitmap in question is returned by the data object from a compiled resource.
internal static System.Drawing.Bitmap folder_page
{
get
{
object obj = ResourceManager.GetObject("folder_page", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
肯特(当然)有正确的答案。 但我想我应该继续发布从 System.Drawing.Bitmap (Windows Forms) 转换为 System.Windows.Windows.Media.BitmapSource (WPF) 的转换器的代码 ..因为这是一个常见的问题。
这需要三个步骤:
以下是如何在绑定中使用图像转换器:
并且,这里是转换器的代码(将其放入名为 ImageConverter.cs 的文件中)并添加它添加到您的项目:
这是您在资源部分中声明它的方式(注意您必须添加的本地命名空间):
就是这样!
更新
在快速搜索类似问题后,我注意到Lars Truijens指出此处转换器实现泄漏。我已经更新了上面的转换器代码......这样它就不会泄漏。
有关泄漏原因的更多信息,请参阅此 MSDN 链接。
Kent (of course) has the right answer. But I thought I would go ahead and post the code for the converter that converts from the System.Drawing.Bitmap (Windows Forms) to a System.Windows.Windows.Media.BitmapSource (WPF) ... as this is a common problem/question.
This takes three steps:
Here is how you would use an image converter in your binding:
And, here is the code for the converter (put it into a file called ImageConverter.cs) and add it to your project:
Here is how you declare it in your resources section (note the local namespace that you will have to add):
And that's it!
Update
After doing a quick search for similar questions, I noticed that Lars Truijens pointed out here that the previous converter implementation leaks. I have updated the converter code above ... so that it doesn't leak.
For more information on the cause of the leak, see the remarks section on this MSDN link.
WPF 使用
ImageSource
类,而不是System.Drawing
类。您需要绑定到ImageSource
。您可以使用转换器将Bitmap
转换为ImageSource
,或者您可以放弃资源并以不同的方式执行操作。WPF works with
ImageSource
s, notSystem.Drawing
classes. You'll need to bind to anImageSource
. You could use a converter to convert yourBitmap
to anImageSource
, or you could ditch the resources and do things differently.WPF 的菜单项有些奇怪,因为它们不与ImageSource 对象,就像 WPF 框架的其余部分一样。
最简单的方法,这会给你带来最少的麻烦,就是在你的视图模型中有一个属性,返回一个完整的 Image 控件:
然后在菜单项的
中(您可以在 ItemContainerStyle 中设置 例如)您只需将菜单项的
Icon
属性绑定到视图模型中的MenuIcon
属性:有人可能会说这破坏了 MVVM 的精神,但在在某些时候,你只需要务实并继续解决更有趣的问题。
WPF's menuitems are somewhat weird in that they don't work with ImageSource objects like the rest of the WPF framework.
The easiest way, that will cause you the least amount of headache is to simply have a property in your viewmodel that returns a full Image control:
And then in your
<Style>
for menu items (which you can set in ItemContainerStyle for example) you simply bind the menu item'sIcon
property to theMenuIcon
property in your viewmodel:One could argue that this breaks the spirit of MVVM, but at some point you just have to be pragmatic and move on to more interesting problems.
以下是我为菜单项创建 ViewModel 的方法: AbstractMenuItem。请特别注意 Icon 区域:
您只需从此类派生,并在构造函数中调用 SetIconFromBitmap 并传入 resx 文件中的图片。
以下是我如何绑定到 工作台窗口:
Here's how I made a ViewModel for a menu item: AbstractMenuItem. Pay particular attention to the Icon region:
You just derive from this class and in the constructor you call SetIconFromBitmap and pass in a picture from your resx file.
Here's how I bound to those IMenuItems in the Workbench Window:
对于后代:我想出了这个:
转换器是
MarkupExtension
和IValueConverter
的组合,因此您可以内联指定它,而不必将其设为静态资源。它使用 System.Windows.Media.ImageSourceConverter 将 uri 转换为 ImageSource,然后使用该源创建一个 Image 控件。
作为奖励,它使用提供给
ProvideValue
的serviceProvider
参数,因此它可以像 WPF 一样解析相对图像 url。For posterity: I've come up with this:
The converter is a combination of
MarkupExtension
and aIValueConverter
, so you can specify it inline without having to make it a static resource.It uses the
System.Windows.Media.ImageSourceConverter
to convert an uri to anImageSource
and then creates anImage
control with that source.As bonus it uses the
serviceProvider
parameter as supplied toProvideValue
so it can resolve relative image urls as WPF would do it.