7

有谁知道是否可以对基于 IValueConverter 的类进行数据绑定?

我有以下转换器:

[ValueConversion(typeof(int), typeof(Article))]
public class LookupArticleConverter : FrameworkElement, IValueConverter {
    public static readonly DependencyProperty ArticlesProperty = DependencyProperty.Register("Articles", typeof(IEnumerable<Article>), typeof(LookupArticleConverter)); 

    public IEnumerable<Article> Articles
    {
        get { return (IEnumerable<Article>)GetValue(ArticlesProperty); }
        set { SetValue(ArticlesProperty, value); }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        ...
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        ...
    }
}

其目的是通过其 Id 在列表中查找文章,并返回该文章。

但是,我想通过将集合数据绑定到它来填充 Articles 属性,如下所示:

<local:LookupArticleConverter Articles="{Binding Articles}" x:Key="LookupArticle"/>

但这似乎不起作用。永远不会调用 setter 方法。source 属性包含一个实际的非空集合,所以这不是问题。

输出日志中也没有关于绑定的错误消息。

有什么线索吗?

4

3 回答 3

10

所以,问题在于资源不是可视化树的一部分。要完成这项工作,您必须:

1.让你的ValueConverter继承Freezable

 public class CustomConverter : Freezable, IValueConverter
 {

    public static readonly DependencyProperty LookupItemsProperty =
        DependencyProperty.Register("LookupItems", typeof(IEnumerable<LookupItem>), typeof(CustomConverter), new PropertyMetadata(default(IEnumerable<LookupItem>)));

    public IEnumerable<LookupItem> LookupItems
    {
        get { return (IEnumerable<LookupItem>)GetValue(LookupItemsProperty); }
        set { SetValue(LookupItemsProperty, value); }
    }

    #region Overrides of Freezable

    /// <summary>
    /// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable"/> derived class.
    /// </summary>
    /// <returns>
    /// The new instance.
    /// </returns>
    protected override Freezable CreateInstanceCore()
    {
        return new CustomConverter();
    }

    #endregion Overrides of Freezable

    // ... Usual IValueConverter stuff ...

}

2. 使用 Binding ElementName 绑定到可视化树

<UserControl (...) x:Name=myUserControl> 
<UserControl.Resources>
<CustomConverter x:Key="customConverter"
                    LookupItems="{Binding ElementName=myUserControl, Path=DataContext.LookupItems}"/>
</UserControl.Resources>
于 2011-12-18T04:22:36.503 回答
3

WPF 本质上并不真正支持这一点。但是,有一些技术可以让您做到这一点,包括 Josh Smith 的虚拟分支方法

于 2009-03-09T09:31:49.510 回答
0

我已将 RelativeSource 方法添加到绑定语句中。这解决了我在 Control.Resources.ResourceDictionary 树下定义了 IValueConverter 的问题,并且我试图从 Control.DataContext 获取 DataContext

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Resources/Text.xaml"/>
            <ResourceDictionary Source="/Resources/Layout.xaml"/>
            <ResourceDictionary Source="/Resources/Colours.xaml"/>
            <ResourceDictionary Source="/Resources/Icons.xaml"/>
        </ResourceDictionary.MergedDictionaries>

        <conv:OrientationConverter x:Key="OerientationConverter" IsOrientationRuleEnabled="{Binding Path=DataContext.IsSiteLayoutPhysical, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, Mode=FindAncestor}}"/>
....
<ListView x:Name="operationsListView" ItemsSource="{Binding .}" DataContext="{Binding GroupedPlantItems}" ItemsPanel="{DynamicResource ItemsPanelTemplate1}" Panel.ZIndex="-10">
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.Panel >
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="{Binding Name, Converter={StaticResource OerientationConverter}}"/>
                        </ItemsPanelTemplate>
                    </GroupStyle.Panel>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <GroupBox Header="{Binding Name}">
                                            <ItemsPresenter/>
                                        </GroupBox>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>
        </ListView>

我在这里很棘手,并根据 IValueConverter 中定义的一些规则来改变 StackPanel 定位其内容的方式。我使用转换器上的绑定来禁用或启用 ViewModel 中的规则。我也可以通过这种方法设置规则,或者传递一个 lambda 表达式进行验证。请原谅我的错别字。

于 2012-01-05T03:37:46.677 回答