[英]Binding string from value of list as StaticResource
当我尝试从后面代码中的列表绑定静态资源名称时,我遇到了一个大问题。
public IDictionary<int, Menuitem> Categories = new Dictionary<int, Menuitem>();
Categories.Add(1, new Menuitem() { Name = "Menu1", Image = "Menu1Resource" });
list.ItemsSource = Categories;
在XAML中
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Icons.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
我想这样绑定
<ListView Padding="20 0" Grid.Row="1" x:Name="list" >
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="#53921D" Margin="0 0 0 10" Padding="15">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="9*"/>
</Grid.ColumnDefinitions>
<Image Source="{StaticResource ResourceKey={Binding Value.Image}}"/>
<TextBlock Grid.Column="1" Foreground="White" Text="{Binding Value.Name}" HorizontalAlignment="Center" FontSize="30" VerticalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
绑定到TextBlock效果很好,但绑定到Image Source却不行。 当我像这样绑定到图像源时
Source="{StaticResource Menu1Resource}"
它也工作,但我想从列表中自动绑定。 谁能给我任何解决这个问题的技巧?;)
据我了解,问题是基于viewmodel数据绑定动态创建Image。 以下是几种解决方案:
您可以将Menuitem模型的图像属性更改为BitmapImage,并使用在viewmodel中创建的Uri路径的实例创建此BitmapImage。
private void Load(object o) { var name = _mFileProvider.GetFileName(); if(string.IsNullOrEmpty(name)) return; ImageSourceBmp = null; ZoomOriginal(); ImageSourceBmp = new BitmapImage(new Uri(name)); } public BitmapImage ImageSourceBmp { get { return _imageSourceBmp; } set { _imageSourceBmp = value; OnPropertyChanged(); } }
您可以使用一些IValueConverter
实现<Image Source="{Binding Value.Image, Converter={StaticResource Path2ImageConverter}}"></Image>
创建从ViewModel到ImageSourse的转换路径。
问候,
在这种情况下,最简单的解决方案是在Menuitem中仅使用相对Uri(就像我在上面评论中发送的文章中一样)。 您可以将工厂共享 ,并在W8.1和WP8.1项目中使用它来创建类别的集合:
public class MenuItem
{
public string Name { get; set; }
public Uri ImageUri { get; set; }
}
public class CategoriesFactory
{
public static IDictionary<int, MenuItem> GetCategories()
{
var categories = new Dictionary<int, MenuItem>();
categories.Add(1, new MenuItem() { Name = "Menu1", ImageUri = new Uri("Icons/image.png", UriKind.RelativeOrAbsolute) });
//add more categories
return categories;
}
}
并直接绑定:
<Image Source="{Binding Value.ImageUri}"/>
也将MenuItem放入共享 。
注意:这只是示例,可以通过多种方式解决,但应该可以。 希望能帮助到你 ;)
StaticResource
仅具有ResourceKey
属性,但这不是DependencyProperty,因此您不能在此处使用Binding。 这里的源当然来自您的视图模型( Value.Image
),但是该源不能直接用于Image的Source
属性。 这意味着我们需要在这里使用一些Converter。 这可以是将输入Value.Image
转换为实际图像源的单向转换器。 Converter应该在视图模型中作为属性公开。 应该有一些服务可以帮助您通过ResourceKey
找到实际的图像源。 这是您应遵循的代码:
public interface IFindResourceService {
object FindResource(object resourceKey);
}
public class FindResourceService : IFindResourceService {
FrameworkElement _element;
public FindResourceService(FrameworkElement startElement){
_element = startElement;
}
public object FindResource(object resourceKey){
return _element.FindResource(resourceKey);
}
}
//the converter
public class ResourceKeyToResourceConverter : IValueConverter {
public IFindResourceService FindResourceService {get;set;}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture){
if(FindResourceService == null) return null;
return FindResourceService.FindResource(value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){
throw new NotImplementedException();
}
}
//your view-model, suppose it inherits from some base view-model
//or implements INotifyPropertyChanged directly ...
public class ViewModel : BaseVM {
public ViewModel(IFindResourceService _service){
ResourceKeyToResource.FindResourceService = _service;
}
public static ResourceKeyToResourceConverter ResourceKeyToResource = new ResourceKeyToResourceConverter();
//... define other properties, members for your view-model normally
//...
}
在初始化视图模型时,您应该使用接受IFindResourceService
类型的服务的构造函数,在这种情况下,您应该可以访问某些FrameworkElement
,与您声明的静态资源相比,该FrameworkElement
在可视树中仍然较低,我认为ListBox
可以用于在此处构造FindResourceService
:
public MainWindow(){
InitializeComponent();
var vm = new ViewModel(new FindResourceService(list));
DataContext = vm;
}
现在,在XAML中,您需要将“ Image
中的绑定Converter
”设置为视图模型的静态属性:
<Image Source="{Binding Value.Image,
Converter={x:Static local:ViewModel.ResourceKeyToResource}}"/>
我假设您将ViewModel
放在命名空间中,并在XAML中声明为local
。
在这一行:
Categories.Add(1, new Menuitem() { Name = "Menu1", Image = "Menu1Resource" });
您可能将ResourceKey Menu1Resource设置为Image,以为您将获得Image对象。
做这个 :
Categories.Add(1, new Menuitem() { Name = "Menu1", Image = _getImgFromResKey("Menu1Resource") });
Image _getImgFromResKey(string key)
{
//access resource from res dictionary
}
最后是<Image Source="{Binding Value.Image}"/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.