繁体   English   中英

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

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

我正在尝试创建一个显示格式化文本的列表框。 我希望能够从代码更改格式。

为了显示格式化文本,我选择了 TextBlock 并打算使用 TextBlock.Inlines 集合进行格式化。 TextBlock.Inlines 不可绑定,因此我创建了从 TextBlock 派生的新 class BindableTextBlock 这个 class 有一个依赖属性InlineList ,我试图将其绑定到Model 中的 InlinesColl ObservableCollection。

问题是InlinesColl中的更改不会将 PropertyChanged 事件通知我的InlineList 绑定仅在BindableTextBlock object 创建时运行一次,此后便不再运行。

任何想法为什么?

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>

可绑定文本块 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

    public class TextBlockModel
    {

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

带有 ListBox ItemSource 集合的 ViewModel

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

在这里测试项目

在你的情况下 - 你没有处理集合中的项目添加\删除的情况
需要 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