我有一个以这种方式构造的组合框的简单模板:
<ComboBox DockPanel.Dock="Left" MinWidth="100" MaxHeight="24"
ItemsSource="{Binding Actions}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Width="100" />
<Image Source="{Binding Converter={StaticResource TypeConverter}}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
所以,如果我使用这段代码,一切都会正常:
<TextBlock Text="{Binding Name}" Width="100" />
<!--<Image Source="{Binding Converter={StaticResource TypeConverter}}" /> -->
<Image Source="{StaticResource SecurityImage}" />
但是如果我使用转换器,它就不再起作用了。 这是转换器,但我不知道如何从那里引用静态资源...
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var type = (Action)value;
var img = new BitmapImage();
switch (type.ActionType)
{
case ActionType.Security:
img.UriSource = new Uri("StructureImage", UriKind.Relative);
break;
case ActionType.Structural:
img.UriSource = new Uri("SecurityImage", UriKind.Relative);
break;
}
return img;
}
尝试使用 Josh 编写的 Switch Converter,应该对你有用:
XAML 的“switch 语句”- http://josheinstein.com/blog/index.php/2010/06/switchconverter-a-switch-statement-for-xaml/
无需编写转换器,您的代码将如下所示 -
<Grid.Resources>
<e:SwitchConverter x:Key="ActionIcons">
<e:SwitchCase When="Security" Then="SecurithImage.png" />
<e:SwitchCase When="Structural" Then="StructureImage.png" />
</e:SwitchConverter>
</Grid.Resources>
<Image Source="{Binding Converter={StaticResource ActionIcons}}" />
这是 SwitchConverter 的代码,因为 Josh 的 网站似乎已关闭 -
/// <summary>
/// A converter that accepts <see cref="SwitchConverterCase"/>s and converts them to the
/// Then property of the case.
/// </summary>
[ContentProperty("Cases")]
public class SwitchConverter : IValueConverter
{
// Converter instances.
List<SwitchConverterCase> _cases;
#region Public Properties.
/// <summary>
/// Gets or sets an array of <see cref="SwitchConverterCase"/>s that this converter can use to produde values from.
/// </summary>
public List<SwitchConverterCase> Cases { get { return _cases; } set { _cases = value; } }
#endregion
#region Construction.
/// <summary>
/// Initializes a new instance of the <see cref="SwitchConverter"/> class.
/// </summary>
public SwitchConverter()
{
// Create the cases array.
_cases = new List<SwitchConverterCase>();
}
#endregion
/// <summary>
/// Converts a value.
/// </summary>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// This will be the results of the operation.
object results = null;
// I'm only willing to convert SwitchConverterCases in this converter and no nulls!
if (value == null) throw new ArgumentNullException("value");
// I need to find out if the case that matches this value actually exists in this converters cases collection.
if (_cases != null && _cases.Count > 0)
for (int i = 0; i < _cases.Count; i++)
{
// Get a reference to this case.
SwitchConverterCase targetCase = _cases[i];
// Check to see if the value is the cases When parameter.
if (value == targetCase || value.ToString().ToUpper() == targetCase.When.ToString().ToUpper())
{
// We've got what we want, the results can now be set to the Then property
// of the case we're on.
results = targetCase.Then;
// All done, get out of the loop.
break;
}
}
// return the results.
return results;
}
/// <summary>
/// Converts a value.
/// </summary>
/// <param name="value">The value that is produced by the binding target.</param>
/// <param name="targetType">The type to convert to.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// Represents a case for a switch converter.
/// </summary>
[ContentProperty("Then")]
public class SwitchConverterCase
{
// case instances.
string _when;
object _then;
#region Public Properties.
/// <summary>
/// Gets or sets the condition of the case.
/// </summary>
public string When { get { return _when; } set { _when = value; } }
/// <summary>
/// Gets or sets the results of this case when run through a <see cref="SwitchConverter"/>
/// </summary>
public object Then { get { return _then; } set { _then = value; } }
#endregion
#region Construction.
/// <summary>
/// Switches the converter.
/// </summary>
public SwitchConverterCase()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SwitchConverterCase"/> class.
/// </summary>
/// <param name="when">The condition of the case.</param>
/// <param name="then">The results of this case when run through a <see cref="SwitchConverter"/>.</param>
public SwitchConverterCase(string when, object then)
{
// Hook up the instances.
this._then = then;
this._when = when;
}
#endregion
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format("When={0}; Then={1}", When.ToString(), Then.ToString());
}
}
使用
Image.UriSource
时,如果图像已添加到您的项目中并且其“构建操作”已设置为“资源”,则需要指定图像的相对文件路径。 例如。如果您已将图像放在 Visual Studio 中名为“images”的项目文件夹中,则可以通过以下方式引用图像:
img.UriSource = new Uri("/Images/StructureImage.png", UriKind.Relative);
如果图像未构建为资源,则必须使用完整文件路径,即
img.UriSource = new Uri("http://server/Images/StructureImage.png", UriKind.Absolute);
编辑:
如果您将图像放入应用程序资源字典中,您始终可以通过以下方式访问它:
Application.Current.Resources["StructureImage"];
如果您将资源放在其他地方,您可以使用
IMultiValueConverter
而不是 IValueConverter
作为转换器。 那么你的类型转换器将如下所示:
class TestValueConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Validation of parameters goes here...
var type = (Action) values[0];
var image1 = values[1];
var image2 = values[2];
if (type.ActionType == ActionType.Security)
{
return image1;
}
else
{
return image2;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
您的 XAML 看起来与此类似:
<Image>
<Image.Source>
<MultiBinding Converter="{StaticResource testValueConverter}">
<Binding Path="Action" />
<Binding Source="{StaticResource SecurityImage}" />
<Binding Source="{StaticResource StructureImage}" />
</MultiBinding>
</Image.Source>
</Image>
最后,这就是您定义资源的方式:
<imaging:BitmapImage x:Key="StructureImage" UriSource="StructureImage.png" />
<imaging:BitmapImage x:Key="SecurityImage" UriSource="SecurityImage.png" />
<local:TestValueConverter x:Key="testValueConverter" />
以上代码未经测试!
虽然接受的答案很好,但我通常会避免“组合框”中带有图像的转换器的复杂性。我通常将图像源 (uri) 的数据类型定义为字符串。这样,就不需要转换器了。下面是一个分步示例:
第1步:创建语言对象类
public class Language
{
public int Id { get; set; }
public string Code { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Uri { get; set; } = string.Empty;
}
第 2 步:在视图模型或隐藏代码中创建语言对象的数组
public class ExampleViewModel
{
private ObservableCollection<Language>? _languages;
public IEnumerable<Language>? Languages => _languages;
public ExampleViewModel()
{
string baseUri = "pack://application:,,,/;component/Images";
// The following static data can also come from the database
_languages =
[
new() { Id = 2, Code = "en-GB", Name = "English", Uri = $"{baseUri}/gb.png" },
new() { Id = 1, Code = "de-DE", Name = "German", Uri = $"{baseUri}/de.png" }
];
}
}
第3步:在视图中创建组合框
XAML:
<ComboBox
x:Name="cbxLanguageSelection"
Margin="0,0,0,0"
HorizontalAlignment="Left"
Background="Transparent"
BorderThickness="0"
ItemsSource="{Binding Languages}"
SelectedItem="{Binding SelectedLanguage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource ResourceKey=ComboBoxStyle}"
ToolTip="Language Selection"
Visibility="Visible">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Style="{StaticResource ResourceKey=DropDownStyle}">
<Image
Height="18"
Margin="0,0,5,0"
Source="{Binding Path=Uri}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
*)请注意,样式和“SelectedLanguage”是可选的。 “SelectedLanguage”属性应在实现时在视图模型或代码隐藏中创建。