【问题标题】:Value Converter not working in Xamarin值转换器在 Xamarin 中不起作用
【发布时间】:2017-06-17 02:30:35
【问题描述】:

这里有点困惑,我似乎已经按照允许我使用值转换器的步骤进行操作。

我用一个键定义了我的转换器,如下所示:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage Title="Article"
                 xmlns="http://xamarin.com/schemas/2014/forms"
                           xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:controls="clr-namespace:XamarinMobile.Controls;assembly=XamarinMobile"
                 xmlns:converters="clr-namespace:XamarinMobile.Converters;assembly=XamarinMobile"
                 x:Class="XamarinMobile.ArticlePage">
      <ContentPage.Resources>
        <ResourceDictionary>
          <converters:FontSizeConverter x:Key="FontSizeMapper"></converters:FontSizeConverter>
        </ResourceDictionary>
      </ContentPage.Resources>

然后我在我的 XAML 中使用我的转换器,如下所示:

          <ContentView Padding="10,-10,10,0" Grid.Row="2" Grid.Column="0">
            <StackLayout>
              <Label x:Name="LabelAuthor" FontSize="{Binding 20, Converter={StaticResource FontSizeMapper}, ConverterParameter=20}" />
              <Label x:Name="LabelPublishDate" FontSize="{Binding 10, Converter={StaticResource FontSizeMapper}, ConverterParameter=10}"/>
            </StackLayout>
          </ContentView>

这是我的实际转换器代码:

namespace XamarinMobile.Converters
{
    public class FontSizeConverter : Xamarin.Forms.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if(value is double)
            {
                return App.NormalizeFontSize((double)value);
            } else
            {
                return value;
            }

        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

然后我在我的值转换器中设置了一个断点,但它从未命中。我在这里有什么明显的遗漏吗?我很确定我是按照指示前往发球台的。

【问题讨论】:

  • 您正在“绑定”到一个静态值(使用Binding 20),我认为您应该在您的BindingContext 对象中绑定一个属性
  • 如果我理解正确,这就是你传递 value 参数的方式。我想传递不同的值,为每个值创建一个属性似乎效率不高。
  • 不,您应该绑定到具有值的属性,但在您的情况下,它不是可用作 FontSize 的值。因此,您需要一个转换器将属性中的值转换为 FontSize。想象一下,您绑定到一个属性,该属性包含字符串中的字体大小,例如"Twenty"FontSize 属性无法理解 "Twenty",因此您需要使用转换器对其进行转换。您绑定到包含字符串值的属性并通过转换器对其进行转换。希望这是有道理的。
  • 感谢您的回复,但是当我在 XAML 中使用它时,如何将其绑定到属性?你是说这个值需要是一个字符串吗?我不明白。我完全理解 fontsize 不理解“二十”,这就是我传递双精度的原因(实际上是一个整数,但可以被视为双精度)。我遇到的问题是,它甚至没有进入我的价值转换器。
  • 我会为此使用附加属性

标签: xamarin xamarin.forms ivalueconverter


【解决方案1】:

由于Gerald Versluis 所说的,您的断点没有被命中。你的绑定坏了。您的绑定的意思是:绑定到BindingContext 上名为“10”的属性,并使用Converter FontSizeMapper,将额外的ConverterParameter 传递给10。“10”不是有效的属性名称,所以绑定正在破坏。如果您查看日志,您应该会看到类似于以下内容的消息:“Binding: '10' property not found on ...”

解决此问题的一种方法是删除您尝试绑定的“路径”并仅使用 ConverterParameter(假设您不需要绑定到任何真实属性):

FontSize="{Binding Converter={StaticResource FontSizeMapper}, ConverterParameter=20}"

请注意,您需要在转换器中使用parameter,而不是value(例如if (parameter is double))。

如果您不需要绑定到任何属性,另一种解决方法是改用自定义标记扩展。

[ContentProperty("FontSize")]
public class FontSizeMapperExtension : IMarkupExtension
{
    public double FontSize { get; set; }

    public object ProvideValue(IServiceProvider serviceProvider)
    {
        return App.NormalizeFontSize(FontSize);
    }
}

然后你可以在你的 XAML 中使用它:

FontSize="{converters:FontSizeMapper FontSize=10}

编辑

绑定到对象属性的示例:

public class YourViewModel
{
    public double VMFontSize { get; set; }
}

public partial class ArticlePage : ContentPage
{
    public ArticlePage()
    {
        InitializeComponent();

        // NOTE: You'd probably get your view-model another way
        var viewModel = new YourViewModel { VMFontSize = 10 };
        BindingContext = viewModel;
    }
}

现在您的视图模型已设置为绑定上下文,您可以像这样设置绑定:

FontSize="{Binding VMFontSize, Converter={StaticResource FontSizeMapper}}"

这就是说:将标签上的 FontSize 属性绑定到当前BindingContext(您的视图模型)上的 VMFontSize 属性,使用转换器在视图模型的 VMFontSize 和标签的 FontSize 之间进行映射。我在此处关闭了 ConverterParameter,因为在此示例中实际上并不需要它,但如果需要,您可以传递一个。

【讨论】:

  • If you don't need to bind to any properties, another way to fix it would be to use a custom markup extension instead. 我想以正确的方式做到这一点。你能告诉我如何将它绑定到一个属性吗?当我的标记在 XAML 中时,我只是有点困惑如何做到这一点。或者也许我完全错了,这就是为什么我想看一个例子。不过谢谢,这帮了大忙。
  • 如果你想绑定到一个属性,它的值被发送到你的转换器,你需要做:FontSize="{Binding YourPropertyName, Converter={StaticResource FontSizeMapper}, ConverterParameter=20}"。该属性需要存在于设置为您页面的BindingContext 的任何内容上。请注意,即使绑定到属性,您仍然可以传递额外的ConverterParameter。如果您仍然需要,我将添加一个更详尽的示例。让我知道!
【解决方案2】:

我会以不同的方式执行此操作,使用自定义附加属性,在此处查看有关附加属性的更多信息https://developer.xamarin.com/guides/xamarin-forms/xaml/attached-properties/

这是你的场景示例,首先我们需要定义一个附加属性,它可以在任何类中,我叫我的 FontHelper

namespace App23
{
    public static class FontHelper
    {
        public static readonly BindableProperty FontSizeProperty =
            BindableProperty.CreateAttached("FontSize", typeof(double), typeof(FontHelper), 0d, propertyChanging:OnPropertyChanging);

        public static bool GetFontSize(BindableObject view)
        {
            return (bool)view.GetValue(FontSizeProperty);
        }

        public static void SetFontSize(BindableObject view, bool value)
        {
            view.SetValue(FontSizeProperty, value);
        }

        private static void OnPropertyChanging(BindableObject bindable, object oldValue, object newValue)
        {
            if (bindable is Label)
            {
                var label = bindable as Label;
                double fontSize = (double)newValue;
                // normalize your font size here
                label.FontSize = fontSize;
            }
        }
    }
}

然后在 XAML 中使用它,它看起来像这样:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:App23"
             x:Class="App23.MainPage">

  <Label Text="Welcome to Xamarin Forms!"
           VerticalOptions="Center"
           HorizontalOptions="Center" local:FontHelper.FontSize="50"/>

</ContentPage>

【讨论】:

    猜你喜欢
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 2016-08-24
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多