【问题标题】:CollectionViewSource View binding does not work for custom controlCollectionViewSource 视图绑定不适用于自定义控件
【发布时间】:2014-02-28 14:04:35
【问题描述】:

您好,我以 MVVM 方式编写了小程序来测试 CollectionViewSource 的使用情况。我有一个包含 ListBox 并具有依赖属性项的 UserControl,它将绑定项从该控件“转发”到 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 和 CollectionViewSource 视图绑定到项目。 它适用于 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 中,如下图所示:

这种行为的原因可能是什么,有什么解决办法吗?

【问题讨论】:

    标签: wpf wpf-controls


    【解决方案1】:

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

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


    CollectionViewSource.View 属性的类型为 ICollectionView,它继承自 IEnumerable 而不是 IEnumerable&lt;string&gt;。因此,源属性类型为IEnumerable,而您的Items DP 类型为IEnumerable&lt;string&gt;。因此,它不起作用。

    而它适用于ObservableCollection&lt;string&gt;,因为它同时实现了IEnumerable&lt;string&gt;IEnumerable

    从上面可以明显看出,所有列表都直接或间接地实现了IEnumerable。所以,你可以做的是让你的 Items DP 类型为 IEnumerable 而不是 IEnumerable&lt;string&gt;,它也适用于 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); }
    }
    

    【讨论】:

    • 非常感谢!它有效,现在很明显:-)。
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2013-03-23
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    相关资源
    最近更新 更多