简体   繁体   English

WPF。将列表框项模板内部绑定到 ObservableCollection 源。 Source PropertyChanged 被忽略

[英]WPF. Binding inside listbox itemtemplate to ObservableCollection source. Source PropertyChanged is ignored

I'm trying to create a ListBox that displays formatted text.我正在尝试创建一个显示格式化文本的列表框。 I want to be able to change formatting from code.我希望能够从代码更改格式。

For displaying formatted text I chose TextBlock and intend to use the TextBlock.Inlines collection for formatting.为了显示格式化文本,我选择了 TextBlock 并打算使用 TextBlock.Inlines 集合进行格式化。 TextBlock.Inlines is not bindable so I created new class BindableTextBlock derived from TextBlock. TextBlock.Inlines 不可绑定,因此我创建了从 TextBlock 派生的新 class BindableTextBlock This class has one dependency property InlineList that I'm trying to bind to InlinesColl ObservableCollection in Model.这个 class 有一个依赖属性InlineList ,我试图将其绑定到Model 中的 InlinesColl ObservableCollection。

The problem is that changes in InlinesColl don't notify my InlineList about PropertyChanged event.问题是InlinesColl中的更改不会将 PropertyChanged 事件通知我的InlineList Binding is functioned just once at BindableTextBlock object creation time and never after.绑定仅在BindableTextBlock object 创建时运行一次,此后便不再运行。

Any ideas why?任何想法为什么?

XAML: XAML:

                <ListBox  x:Name="PART_lb" VerticalAlignment="Stretch" ItemsSource="{Binding ItemColl}"
                            ScrollViewer.HorizontalScrollBarVisibility="Auto" 
                            ScrollViewer.VerticalScrollBarVisibility="Auto" >
                    
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <local:BindableTextBlock InlineList="{Binding Path=InlinesColl}" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                    
                </ListBox>

BindableTextBlock class:可绑定文本块 class:

 public class BindableTextBlock : TextBlock
    {
        public ObservableCollection<Inline> InlineList
        {
            get { return (ObservableCollection<Inline>)GetValue(InlineListProperty); }
            set { SetValue(InlineListProperty, value); }
        }

        public static readonly DependencyProperty InlineListProperty =
            DependencyProperty.Register("InlineList", typeof(ObservableCollection<Inline>), typeof(BindableTextBlock), new UIPropertyMetadata(null, OnPropertyChanged));

        private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            BindableTextBlock textBlock = (BindableTextBlock)sender;
            textBlock.Inlines.Clear();
            textBlock.Inlines.AddRange((ObservableCollection<Inline>)e.NewValue);
        }

      
    }

Model class Model class

    public class TextBlockModel
    {

        ObservableCollection<Inline> _inlinesColl = new ObservableCollection<Inline>();
        public ObservableCollection<Inline> InlinesColl
        {
            get { return _inlinesColl; }
            set {_inlinesColl = value; }
        }
    }

ViewModel with collection for ListBox ItemSource带有 ListBox ItemSource 集合的 ViewModel

        ObservableCollection<TextBlockModel> _itemColl = new ObservableCollection<TextBlockModel>();
        public ObservableCollection<TextBlockModel> ItemColl
        {
            get { return _itemColl; }
            set { _itemColl = value; }
        }

Test project here 在这里测试项目

In your case - you didn't handle case when item inside collection added\deleted在你的情况下 - 你没有处理集合中的项目添加\删除的情况
Need go deeply and subscirbe to CollectionChanged when new collection will be assigned.需要 go 并在分配新集合时订阅 CollectionChanged。

 public class BindableTextBlock : TextBlock
    {
        static int Cntr = 0;
        public BindableTextBlock()
        {
            Console.WriteLine("BindableTextBlock constructor " + Cntr);
            Cntr++;
        }

        public ObservableCollection<Inline> InlineList
        {
            get { return (ObservableCollection<Inline>)GetValue(InlineListProperty); }
            set { SetValue(InlineListProperty, value); }
        }

        public static readonly DependencyProperty InlineListProperty =
            DependencyProperty.Register("InlineList", typeof(ObservableCollection<Inline>), typeof(BindableTextBlock), new UIPropertyMetadata(null, OnPropertyChanged));

        private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            BindableTextBlock textBlock = (BindableTextBlock)sender;

            // subscribe to collection changed
            textBlock.UpdateInlineListSource((ObservableCollection < Inline > )e.OldValue, (ObservableCollection < Inline > )e.NewValue);

        }

        public void UpdateInlineListSource(ObservableCollection<Inline> oldCollection, ObservableCollection<Inline> newCollection)
        {
            if (oldCollection!=null)
            oldCollection.CollectionChanged -= OnCollectionChanged;

            if (newCollection != null)
            {
                newCollection.CollectionChanged += OnCollectionChanged;
                OnCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                OnCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newCollection));
            }
        }

        private void OnCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            var newItems = e.NewItems?.Cast<Inline>()?.ToList() ?? new List<Inline>();
            var oldItems = e.OldItems?.Cast<Inline>()?.ToList() ?? new List<Inline>();

            // changed source
            if (e.Action==NotifyCollectionChangedAction.Reset)
                this.Inlines.Clear();

            foreach (var itemForDelete in oldItems)
            {
                if (this.Inlines.Contains(itemForDelete))
                    this.Inlines.Remove(itemForDelete);
            }

            foreach (var itemsForAdd in newItems)
            {
                this.Inlines.Add(itemsForAdd);
            }
        }
    }

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

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