简体   繁体   English

如何在 Silverlight XAML 中引用另一个名称空间中的绑定转换器?

[英]How can I refer to a binding converter in another namespace in Silverlight XAML?

Since you apparently can't create a Silverlight DataTemplate in C#, I'm trying to create one in XAML. I have a converter that I need to refer to, that I have defined in C# in another namespace.由于您显然无法在 C# 中创建 Silverlight DataTemplate,因此我正在尝试在 XAML 中创建一个。我有一个需要参考的转换器,我在另一个命名空间中的 C# 中定义了它。 I've tried doing this:我试过这样做:

<UserControl.Resources>
        <DataTemplate x:Key="PriceTemplate">
            <TextBlock Text="{Binding Price, Converter={Converters:PriceConverter}}" />
        </DataTemplate>
    </UserControl.Resources>

Where Converters is an xmlns that points to the correct namespace.其中 Converters 是指向正确命名空间的 xmlns。 However, I get a compilation error that says:但是,我收到一个编译错误:

Type 'Converters:PriceConverter' is used like a markup extension but does not derive from MarkupExtension.类型“Converters:PriceConverter”像标记扩展一样使用,但不是从 MarkupExtension 派生的。

I tried adding System.Windows.Markup.MarkupExtension as a parent to my converter, but it apparently doesn't exist in Silverlight.我尝试将 System.Windows.Markup.MarkupExtension 作为父级添加到我的转换器中,但它显然不存在于 Silverlight 中。

How can I refer to my converter in XAML, without having to rewrite it in XAML?我如何在 XAML 中引用我的转换器,而不必在 XAML 中重写它?

You want to make a static resource first, then bind to the converter that is a static resource.您要先制作静态资源,然后绑定到作为静态资源的转换器。

 <UserControl.Resources> 
   <conv:IntConverter x:Key="IntConverter"></conv:IntConverter> 
 </UserControl.Resources> 
 <StackPanel> 
    <TextBlock x:Name="Result" Margin="15" FontSize="20" 
              HorizontalAlignment="Center" VerticalAlignment="Center" 
               Text="{Binding Converter={StaticResource IntConverter}}"> 
    </TextBlock> 
 </StackPanel> 
</Window>

So the "conv:" xml namespace was registered at the top of the document like you do with custom controls:所以 "conv:" xml 命名空间注册在文档的顶部,就像使用自定义控件一样:

xmlns:conv="clr-namespace:MyFooCompany.Converters"

This example is adapted from the below linked tutorial regarding the same issue for WPF:此示例改编自以下有关 WPF 相同问题的链接教程:

http://www.dev102.com/2008/07/17/wpf-binding-converter-best-practices/ http://www.dev102.com/2008/07/17/wpf-binding-converter-best-practices/

You seem to be confusing Types with Instances.您似乎将类型与实例混淆了。 A converter type will exist "in" a namespace however in binding we do not specify a type as the converter.转换器类型将存在于命名空间中,但是在绑定中我们没有指定类型作为转换器。 Instead we give the binding an actual instance of that type.相反,我们为绑定提供了该类型的实际实例。

Generally IValueConverter instances are stateless, hence we can hold a common instance anywhere in a the chain of resource dictionaries available where the instance of a DataTemplate is loaded.通常IValueConverter实例是无状态的,因此我们可以在加载 DataTemplate 实例的可用资源字典链中的任何位置保存一个公共实例。

In xaml we can reference another namespace by creating a new alias to cover it.在 xaml 中,我们可以通过创建一个新别名来引用另一个命名空间来覆盖它。 With that in mind your xaml could look something like this:-考虑到这一点,您的 xaml 可能如下所示:-

<UserControl x:Class="SilverlightApplication1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SilverlightApplication1"
    xmlns:localConverters="clr-namespace:SilverlightApplication1.Converters">
    <UserControl.Resources>
        <localConverters:PriceConverter x:Key="PriceConverter" />
        <DataTemplate x:Key="Test">
            <TextBlock Text="{Binding Price, Converter={StaticResource PriceConverter}}" />
        </DataTemplate>
    </UserControl.Resources>
<RadioButton GroupName="Group1">
    <RadioButton.Template>
        <ControlTemplate>
            <ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
                <ToggleButton.Content>
                    <SymbolIcon Symbol="Edit"/>
                </ToggleButton.Content>
                <ToolTipService.ToolTip>
                    <ToolTip Content="Sample Tooltip" Placement="Mouse" />
                </ToolTipService.ToolTip>
            </ToggleButton>
        </ControlTemplate>
    </RadioButton.Template>
</RadioButton>

Adding to the answer posted by @Rokk.添加到@Rokk 发布的答案中。

In addition to the other answers suggesting creating an instance of the ValueConverter in a resource dictionary, another solution is to implement it via a MarkupExtention:除了建议在资源字典中创建 ValueConverter 实例的其他答案之外,另一种解决方案是通过 MarkupExtention 实现它:

public class IntToLetterConverter : IMarkupExtension<IValueConverter>, IValueConverter
{
    public IValueConverter ProvideValue(IServiceProvider serviceProvider)
        => (IValueConverter)this;

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
        => ((IMarkupExtension<IValueConverter>)this).ProvideValue(serviceProvider);

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => (char)('a' + (int)value);

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => (int)((char)value - 'a');
}

With this solution you can directly reference the converter (which is in essence a MarkupExtension) whithout defining a resource.使用此解决方案,您可以直接引用转换器(本质上是一个 MarkupExtension)而无需定义资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM