【问题标题】:How do I bind the name of a StaticResource to a ViewModel property?如何将 StaticResource 的名称绑定到 ViewModel 属性?
【发布时间】:2020-03-25 12:07:10
【问题描述】:

我有一个场景,我的 Xamarin 标签显示来自 ttf 文件的图标。就目前而言,标签如下所示。

<Label
Text="{StaticResource Account}"/>

Account 是我的 Styles.xaml 文件中定义十六进制值的字符串。

<x:String x:Key="Account">&#xe70e;</x:String>

以上工作正常。但是,我想通过 ViewModel 中的属性绑定图标文本名称。以下不起作用,但我正在考虑这样的事情:

 Text="{StaticResource Binding=IconName}"

我将如何做到这一点?

更新:为这个问题添加更多上下文。

在我的 Styles.xaml 中,我定义了一个与其十六进制值相对应的字典

<x:String x:Key="Back">&#xe709;</x:String>
<x:String x:Key="Share">&#xe704;</x:String>
<x:String x:Key="Next">&#xe71a;</x:String>
<x:String x:Key="Account">&#xe70e;</x:String>
<x:String x:Key="Bell">&#xe700;</x:String>
<x:String x:Key="Mail">&#xe70e;</x:String>
<x:String x:Key="Help">&#xe72c;</x:String>

此样式文件是我的 xaml 文件的资源。

        <ContentPage.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Styles.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </ContentPage.Resources>

在我的 XAML 文件中,我正在迭代以显示不同的图标。

            <StackLayout
                x:Name="ItemsList"
                Grid.Row="1"
                BindableLayout.ItemsSource="{Binding MenuItems}">
                <BindableLayout.ItemTemplate>
                    <DataTemplate>
                        <StackLayout>
                            <Label  Text="{StaticResource Account}" FontFamily="{StaticResource FontIcons}"
                                FontSize="Large"></Label>
                        </StackLayout>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </StackLayout>

在我的列表中,我指定了图标名​​称。

        MenuItems = new List<AppMenuItem>()
        {
            new AppMenuItem()
            {
                Title = "View A",
                IconSource = "Account",
            },
            new AppMenuItem()
            {
                Title = "View B",
                IconSource = "Mail",
            }

        };

更新 2:我正在尝试构建一个值转换器,但我似乎无法访问合并的字典。我正在使用:

Application.Current.Resources.TryGetValue(value.ToString(), out var retValue);

retValue 总是返回 NULL。

【问题讨论】:

  • 如果是虚拟机属性,请使用"{Binding IconName}"
  • 这不太行,因为它只是绑定到一个字符串属性 IconName。实际资源是静态资源。
  • 然后让你的属性的getter返回资源值
  • 我用更多上下文更新了原始问题
  • 使用 ValueConverter

标签: xamarin mvvm xamarin.forms


【解决方案1】:

你可以使用数据触发器,

<Label Text="">
     <Label.Triggers>
        <DataTrigger TargetType="Label"
                  Binding="{Binding IconName}"
                  Value="Account">
                  <Setter Property="Text" Value="{StaticResource Account}"/>
         </DataTrigger>
     </Label.Triggers>
</Label>

您可以为每个要匹配的条件编写多个 DataTriggers 并设置 StaticResource

【讨论】:

    【解决方案2】:

    您可以绑定到标签的样式。

    <Style TargetType="Label">
        <Setter Property="Text" Value="{Binding Account}"/>
    </Style>
    

    【讨论】:

    • 我没有绑定到样式,我正在尝试更新文本绑定
    • 那么你可以不使用字符串直接完成
    【解决方案3】:
        -----:::App.xaml:::------
     <?xml version="1.0" encoding="utf-8" ?>
        <Application xmlns="http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     x:Class="PracticeXamarinForms.App">
            <Application.Resources>
                <ResourceDictionary>
                    <x:String x:Key="Back">&#xe709;</x:String>
                    <x:String x:Key="Share">&#xe704;</x:String>
                    <x:String x:Key="Next">&#xe71a;</x:String>
                    <x:String x:Key="Account">&#xe70e;</x:String>
                    <x:String x:Key="Bell">&#xe700;</x:String>
                    <x:String x:Key="Mail">&#xe70e;</x:String>
                    <x:String x:Key="Help">&#xe72c;</x:String>
                </ResourceDictionary>
            </Application.Resources>
        </Application>
    
        -----:::Views:::------
        <?xml version="1.0" encoding="utf-8" ?>
        <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     x:Class="PracticeXamarinForms.Views.DemoPage"
                     xmlns:vm="clr-namespace:PracticeXamarinForms.ViewModels">
            <ContentPage.BindingContext>
                <vm:DemoViewModel/>
            </ContentPage.BindingContext>
            <ContentPage.Content>
                <StackLayout>
                    <Label 
                        VerticalOptions="CenterAndExpand" 
                        HorizontalOptions="CenterAndExpand"
                           Text="{Binding IconName}"/>
                </StackLayout>
            </ContentPage.Content>
        </ContentPage>
    
        -----:::ViewModels:::------
        using System;
        using System.Collections.Generic;
        using System.Text;
    
        namespace PracticeXamarinForms.ViewModels
        {
            public class DemoViewModel
            {
                #region properties
                public string IconName { get; set; }
                #endregion
    
                public DemoViewModel()
                {
                    IconName = (string)App.Current.Resources["Mail"];
                }
            }
        }
    

    【讨论】:

    • 这几乎让我到了那里,问题是我正在遍历一个列表以在 xaml 中显示图标。我在原始问题中添加了更多上下文。
    • 如果您将密钥放在 ContePage.ResourceDictionary 中,您如何从后面的代码中访问这些密钥?
    【解决方案4】:

    为图标字形定义类:

    namespace MyNamespace
    {
        public static class Icons
        {
            public const string Glyph = "\ue000";
            ...
        }
    }
    

    资源字典/Resources/Glyphs.xaml:

    <ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                        xmlns:i="clr-namespace:MyNamespace">
    
        <OnPlatform x:Key="Glyph" x:TypeArguments="x:String" Default="{x:Static i:Icons.Glyph}" />
    
    </ResourceDictionary>
    

    从页面引用资源字典:

    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Resources/Glyphs.xaml" />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    

    ViewModel 示例:

    using MyNamespace;
    ...
    public class FontViewModel
    {
        public string GlyphFromClass { get; set; }
    
        public string GlyphFromMergedResource { get; set; }
    
        //pass page in constructor for referencing the page local resource dictionary
        public FontViewModel(Page page)
        {
            GlyphFromClass = Icons.Glyph;
    
            //ResourceDictionary applicationResourceDictionary = Application.Current.Resources;
    
            ResourceDictionary localResourceDictionary = page.Resources;
    
            string str = string.Empty;
            if (localResourceDictionary.TryGetValue("Glyph", out object obj) && obj is OnPlatform<string>)
            {
                str = (OnPlatform<string>)obj;
            }
    
            GlyphFromMergedResource = str;
        }
    }
    

    如果需要,为 viewmodel 类实现 INotifyPropertyChanged 并在属性中使用 OnPropertyChanged

    页面xaml代码后面的Viewmodel使用示例:

    InitializeComponent();
    
    BindingContext = new FontViewModel(this);
    

    带绑定的 Xaml:

    <Label Text="{Binding GlyphFromClass}" FontFamily="{StaticResource FontFamily}" />
    <Label Text="{Binding GlyphFromMergedResource}" FontFamily="{StaticResource FontFamily}" />
    

    带有静态资源的 Xaml:

    <Label Text="{x:Static i:Icons.Glyph}" FontFamily="{StaticResource FontFamily}" />
    <Label Text="{StaticResource Glyph}" FontFamily="{StaticResource FontFamily}" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-26
      • 2015-11-24
      • 2010-10-16
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多