CollectionViewSource View绑定不适用于自定义控件

时间:2014-02-04 14:33:20

标签: wpf wpf-controls

您好我已经编写了MVVM方式的小程序来测试CollectionViewSource的用法。我有一个UserControl包含ListBox并具有依赖属性项,它将此控件中的绑定项“转发”到ListBox ItemsSource:

<UserControl x:Class="TestingCollectionViewSource.TestControlWithListBox"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:TestingCollectionViewSource="clr-namespace:TestingCollectionViewSource" 
                mc:Ignorable="d" 
                d:DesignHeight="300" d:DesignWidth="300">
       <Grid>
           <ListBox ItemsSource="{Binding Items,
           RelativeSource={RelativeSource AncestorType=TestingCollectionViewSource:TestControlWithListBox}}" />
       </Grid>
   </UserControl>


public partial class TestControlWithListBox : UserControl
    {
        public static readonly DependencyProperty ItemsProperty =
            DependencyProperty.Register("Items", typeof (IEnumerable<string>), typeof (TestControlWithListBox), new PropertyMetadata(default(IEnumerable<string>)));

        public IEnumerable<string> Items
        {
            get { return (IEnumerable<string>) GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }

        public TestControlWithListBox()
        {
            InitializeComponent();
        }
    }

我尝试使用ObservableCollection和ViewViewSource绑定到Items。 它适用于ObservableCollection,但不适用于CollectionViewSource。

<Window x:Class="TestingCollectionViewSource.MainWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:TestingCollectionViewSource="clr-namespace:TestingCollectionViewSource" Width="500" Height="500">
    <Grid>
        <TestingCollectionViewSource:TestControlWithListBox Items="{Binding Path=ItemsCollectionViewSource.View}"/>
    </Grid>
</Window>

public class MainWindowViewModel : Screen
{
    private ObservableCollection<string> items;

    public ObservableCollection<string> Items
    {
        get { return items; }
        set
        {
            items = value;
            NotifyOfPropertyChange(() => Items);
        }
    }

    private CollectionViewSource itemsCollectionViewSource;

    public CollectionViewSource ItemsCollectionViewSource
    {
        get { return itemsCollectionViewSource; }
        set
        {
            itemsCollectionViewSource = value;
            NotifyOfPropertyChange(() => ItemsCollectionViewSource);
        }
    }

    public MainWindowViewModel()
    {
        DisplayName = "Testing testing testing";
        Items = new ObservableCollection<string>()
            {
                "1",
                "2 2",
                "3 3 3",
                "4 4 4 4"
            };

        ItemsCollectionViewSource = new CollectionViewSource() { Source = Items};
    }
}

但是如果我尝试将CollectionViewSource.View绑定到ListBox没有问题,所有列表项都包含在ListBox中,如下图所示:

CollectionViewSource Test

这种行为可能是什么原因,是否有任何解决方案?

1 个答案:

答案 0 :(得分:4)

要使绑定工作,源属性和目标属性应该是相同的数据类型。

如果仔细查看“输出”窗口,您将看到针对源和目标属性的不匹配数据类型记录的绑定错误。


CollectionViewSource.View属性属于ICollectionView类型,它继承自IEnumerable而非IEnumerable<string>。因此,源属性类型为IEnumerable,而您的Items DP属于IEnumerable<string>类型。因此,它不起作用。

虽然它适用于ObservableCollection<string>,因为它同时实现了IEnumerable<string>IEnumerable

从上面可以看出,所有列表都直接或间接地实现了IEnumerable。所以,你可以做的是使你的Items DP类型为IEnumerable而不是IEnumerable<string>,它也适用于CollectionViewSource。

public static readonly DependencyProperty ItemsProperty =
      DependencyProperty.Register("Items", typeof (IEnumerable),
    typeof (TestControlWithListBox), new PropertyMetadata(default(IEnumerable)));

public IEnumerable<string> Items
{
   get { return (IEnumerable) GetValue(ItemsProperty); }
   set { SetValue(ItemsProperty, value); }
}