WPF MVVM中列表中的图像
我有一个关于如何在WPF MVVM中最好地完成某些事情的问题。我的ViewModel中有一系列整数。为了举例,让我们称之为:WPF MVVM中列表中的图像,wpf,image,data-binding,mvvm,Wpf,Image,Data Binding,Mvvm,我有一个关于如何在WPF MVVM中最好地完成某些事情的问题。我的ViewModel中有一系列整数。为了举例,让我们称之为: public int Yellow { get;set; } public int Red { get;set; } public int Green { get;set; } 我也有一些非常简单的小图片:一个红色的圆圈,一个黄色的圆圈和一个绿色的圆圈。其思想是基于上述属性,在视图上有一个区域,其中包含许多这样的图像。所以,如果视图模型的这个实例
public int Yellow
{
get;set;
}
public int Red
{
get;set;
}
public int Green
{
get;set;
}
我也有一些非常简单的小图片:一个红色的圆圈,一个黄色的圆圈和一个绿色的圆圈。其思想是基于上述属性,在视图上有一个区域,其中包含许多这样的图像。所以,如果视图模型的这个实例有3个黄色、2个红色和1个绿色,我希望列表框中有6个图像,3个黄色圆圈,2个红色,1个绿色。现在,我已经让它工作了,但是使用了一些非常笨拙的代码,在ViewModel中使用丑陋的for循环构建图像列表。在WPF中是否有更优雅的方法来完成此任务?理想情况下,我根本不想在ViewModel中引用图像…您可以使用平铺图像来平铺矩形,并将矩形的宽度绑定到所需图像的副本数。大概是这样的:
<StackPanel Orientation="Horizontal">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="20" ScaleY="20"/>
</StackPanel.LayoutTransform>
<Rectangle Width="{Binding Yellow}" Height="1">
<Rectangle.Fill>
<ImageBrush
ImageSource="Yellow.png"
Viewport="0,0,1,1"
ViewportUnits="Absolute"
TileMode="Tile"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Width="{Binding Red}" Height="1">
<Rectangle.Fill>
<ImageBrush
ImageSource="Red.png"
Viewport="0,0,1,1"
ViewportUnits="Absolute"
TileMode="Tile"/>
</Rectangle.Fill>
</Rectangle>
<Rectangle Width="{Binding Green}" Height="1">
<Rectangle.Fill>
<ImageBrush
ImageSource="Green.png"
Viewport="0,0,1,1"
ViewportUnits="Absolute"
TileMode="Tile"/>
</Rectangle.Fill>
</Rectangle>
</StackPanel>
更新:正如Ray在评论中指出的,如果您只是尝试绘制圆,那么使用DrawingBrush比使用图像可以获得更好的缩放效果:
<StackPanel Orientation="Horizontal">
<StackPanel.LayoutTransform>
<ScaleTransform ScaleX="20" ScaleY="20"/>
</StackPanel.LayoutTransform>
<StackPanel.Resources>
<EllipseGeometry x:Key="Circle" RadiusX="1" RadiusY="1"/>
</StackPanel.Resources>
<Rectangle Width="{Binding Yellow}" Height="1">
<Rectangle.Fill>
<DrawingBrush ViewportUnits="Absolute" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing
Brush="Yellow"
Geometry="{StaticResource Circle}"/>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
<!-- etc. -->
一种可能是使用。它非常灵活、解耦,有助于简化xaml。以下是此类值转换器的代码:
public class ImageCountValueConverter : IValueConverter{
public string ImagePath {
get;
set;
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
if(null == value){
return Enumerable.Empty<string>();
} else if (value is int) {
List<string> list = new List<string>();
int v = (int)value;
for (int i = 0; i < v; i++) {
if (parameter is string) {
list.Add((string)parameter);
} else {
list.Add(ImagePath);
}
}
return list;
} else {
Type t = value.GetType();
throw new NotSupportedException("The \"" + t.Name+ "\" type is not supported");
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
公共类ImageCountValueConverter:IValueConverter{
公共字符串映像路径{
收到
设置
}
公共对象转换(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性){
if(null==值){
返回可枚举的.Empty();
}else if(值为int){
列表=新列表();
int v=(int)值;
对于(int i=0;i
标记如下所示:
<StackPanel>
<ItemsControl ItemsSource="{Binding Yellow,Converter={StaticResource ImageCount_ValueConverter},ConverterParameter=/image/yellow.png}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Stretch="None"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding Red,Converter={StaticResource ImageCount_ValueConverter},ConverterParameter=/image/red.png}" >
...
...
该宣言将类似于:
<Window.Resources>
<local:ImageCountValueConverter x:Key="ImageCount_ValueConverter" ImagePath="/image/sampleImage.png"/>
</Window.Resources>
选项
根据您的要求,您还可以将其扩展或更改为使用ImageSource而不是字符串,甚至可以提供一个
列表作为输出,然后在数据模板中使用一个形状,在该形状中通过绑定设置笔刷。这看起来是可行的。还有其他解决方案吗?Quartermeister的解决方案基本上与我的建议(+1)相同。还有其他的解决方案,但没有一个这么干净、简单和优雅。你对他的回答不满意有什么原因吗?我确实想到了对Quartermeister解决方案的一个可能的改进:如果使用带有圆形图形的DrawingBrush,而不是带有.png文件的ImageBrush,你会获得更好的缩放效果@夸特迈斯特:如果你愿意的话,欢迎你在回答中加上这个。@Ray:说得好!他说他有图像,所以我在考虑图像文件,但如果它们真的只是圆,那么DrawingBrush会更简单。我会更新我的答案。我对答案不是太不满意,而是想进一步了解WPF的总体情况。在我的研究中,我遇到了几个可能工作的组件(值转换器、触发器、画笔等),并希望得到一系列包含不同技术的不同示例。