将列表值中的字符串绑定为静态资源

本文关键字:绑定 静态 资源 字符串 列表 | 更新日期: 2023-09-27 18:18:18

当我尝试从代码隐藏中的列表中绑定静态资源的名称时,我遇到了一个大问题。

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>

绑定到文本块效果很好,但绑定到图像源则不然。当我绑定到图像源时,例如

Source="{StaticResource Menu1Resource}"

它也可以工作,但我想从列表中自动绑定。任何人都可以给我解决这个问题的任何提示吗;)

将列表值中的字符串绑定为静态资源

在这一行中:

Categories.Add(1, new Menuitem() { Name = "Menu1", Image = "Menu1Resource" });

您可能将资源键菜单1资源设置为图像,认为您将获得图像对象。

这样做:

Categories.Add(1, new Menuitem() { Name = "Menu1", Image = _getImgFromResKey("Menu1Resource") });
Image _getImgFromResKey(string key)
{
   //access resource from res dictionary
}

最后<Image Source="{Binding Value.Image}"/>

如何从Res字典中获取资源

据我了解,问题是基于视图模型数据绑定动态创建图像。以下是几种解决方案:

  1. 您可以将菜单项模型的图像属性更改为位图图像,并使用在视图模型中创建的 Uri 路径实例创建此位图图像。

        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();
        }
    }
    
  2. 您可以使用一些IValueConverter实现<Image Source="{Binding Value.Image, Converter={StaticResource Path2ImageConverter}}"></Image>创建从视图模型接收的路径

问候

在这种情况下,最简单的解决方案是在菜单项中仅使用相对 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}"/>

将菜单项也放入共享中。

注意:这只是样本,可以通过多种方式解决,但它应该可以工作。希望对;)有所帮助

StaticResource只有属性ResourceKey但这不是依赖属性,因此不能在此处使用绑定。这里的源当然来自您的视图模型(Value.Image(,但该源不能直接用于图像的Source属性。这意味着我们需要在这里使用一些转换器。这可以只是一个单向转换器,用于将输入Value.Image转换为实际的图像源。转换器应作为视图模型中的属性公开。应该有一些服务可以帮助通过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,我假设ListBox可用于在此处构造FindResourceService

public MainWindow(){
   InitializeComponent();
   var vm = new ViewModel(new FindResourceService(list));
   DataContext = vm;
}

现在,在 XAML 中,您需要将绑定的Converter设置为 Image 视图模型的静态属性:

<Image Source="{Binding Value.Image, 
                Converter={x:Static local:ViewModel.ResourceKeyToResource}}"/>

我假设您将ViewModel放在命名空间中,并将其声明为 XAML 中的local