值转换器在 Xamarin 中不起作用
Value Converter not working in Xamarin
这里有点困惑,我似乎已经遵循了允许我使用值转换器的步骤。
我用密钥定义了我的转换器,因此:
<?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();
}
}
}
然后我在我的值转换器中放置了一个断点,但它从未命中。有什么明显的东西我在这里失踪了吗?我很确定我是按照指示去发球台的。
由于 所说,您的断点未被命中。你的绑定坏了。你的绑定说的是:绑定到 BindingContext
上名为“10”的 属性,并使用 Converter
FontSizeMapper,将额外的 ConverterParameter
传递给它 10。” 10" 不是有效的 属性 名称,因此绑定中断。如果查看日志,您应该会看到类似于以下内容的消息:"Binding: '10' property not found on ..."
修复它的一种方法是删除您尝试绑定的 "Path" 并仅使用 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;
}
}
现在您的 view-model 已设置为绑定上下文,您可以像这样设置绑定:
FontSize="{Binding VMFontSize, Converter={StaticResource FontSizeMapper}}"
这里说的是:将标签上的FontSize属性绑定到当前BindingContext
(你的view-model)上的VMFontSize属性,使用转换器来view-model 的 VMFontSize 和 Label 的 FontSize 之间的映射。我把 ConverterParameter
去掉了,因为在这个例子中它并不是真正需要的,但是如果你需要的话你可以传递一个。
我会以不同的方式执行此操作,使用自定义附加 属性,请在此处查看有关附加属性的更多信息 https://developer.xamarin.com/guides/xamarin-forms/xaml/attached-properties/
这是您的场景示例,首先我们需要定义一个附加的 属性,它可以是任何 class,我叫我的 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>
这里有点困惑,我似乎已经遵循了允许我使用值转换器的步骤。
我用密钥定义了我的转换器,因此:
<?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();
}
}
}
然后我在我的值转换器中放置了一个断点,但它从未命中。有什么明显的东西我在这里失踪了吗?我很确定我是按照指示去发球台的。
由于 BindingContext
上名为“10”的 属性,并使用 Converter
FontSizeMapper,将额外的 ConverterParameter
传递给它 10。” 10" 不是有效的 属性 名称,因此绑定中断。如果查看日志,您应该会看到类似于以下内容的消息:"Binding: '10' property not found on ..."
修复它的一种方法是删除您尝试绑定的 "Path" 并仅使用 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;
}
}
现在您的 view-model 已设置为绑定上下文,您可以像这样设置绑定:
FontSize="{Binding VMFontSize, Converter={StaticResource FontSizeMapper}}"
这里说的是:将标签上的FontSize属性绑定到当前BindingContext
(你的view-model)上的VMFontSize属性,使用转换器来view-model 的 VMFontSize 和 Label 的 FontSize 之间的映射。我把 ConverterParameter
去掉了,因为在这个例子中它并不是真正需要的,但是如果你需要的话你可以传递一个。
我会以不同的方式执行此操作,使用自定义附加 属性,请在此处查看有关附加属性的更多信息 https://developer.xamarin.com/guides/xamarin-forms/xaml/attached-properties/
这是您的场景示例,首先我们需要定义一个附加的 属性,它可以是任何 class,我叫我的 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>