WPF textblock binding with List

后端 未结 4 1823
-上瘾入骨i
-上瘾入骨i 2020-11-29 08:48

does anyone know if there is a simple way to bind a textblock to a List. What I\'ve done so far is create a listview and bind it to the List and then I have a template withi

4条回答
  •  醉话见心
    2020-11-29 09:26

    if you use the converter it works for the first time perfect, but if one or more logging comes to the logging list, there is no update on your binding, because the converter works only at the first time. all controls that are no item controls doesn't subscribe to the listchanged event!

    here is a little code for this scenario

    using System;
    using System.Collections.ObjectModel;
    using System.Windows;
    
    namespace BindListToTextBlock
    {
      /// 
      /// Interaction logic for MainWindow.xaml
      /// 
      public partial class MainWindow : Window
      {
        private WorkItem workItem;
    
        public MainWindow() {
          this.WorkItems = new ObservableCollection();
          this.DataContext = this;
          this.InitializeComponent();
        }
    
        public class WorkItem
        {
          public WorkItem() {
            this.Logs = new ObservableCollection();
          }
    
          public string Name { get; set; }
          public ObservableCollection Logs { get; private set; }
        }
    
        public ObservableCollection WorkItems { get; set; }
    
        private void Button_Click(object sender, RoutedEventArgs e) {
          this.workItem = new WorkItem() {Name = string.Format("new item at {0}", DateTime.Now)};
          this.workItem.Logs.Add("first log");
          this.WorkItems.Add(this.workItem);
        }
    
        private void Button_Click_1(object sender, RoutedEventArgs e) {
          if (this.workItem != null) {
            this.workItem.Logs.Add(string.Format("more log {0}", DateTime.Now));
          }
        }
      }
    }
    

    the xaml

    
      
        
          
        
        
          
          
          
        
        

    the converter

    using System;
    using System.Collections;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Data;
    
    namespace BindListToTextBlock
    {
      public class ListToStringConverter : IValueConverter
      {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
          if (value is IEnumerable) {
            return string.Join(Environment.NewLine, ((IEnumerable)value).OfType().ToArray());
          }
          return "no messages yet";
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
          return DependencyProperty.UnsetValue;
        }
      }
    }
    

    EDIT

    here is a quick solution for the update propblem (this can be also made with a attached property)

    public class CustomTextBlock : TextBlock, INotifyPropertyChanged
    {
      public static readonly DependencyProperty ListToBindProperty =
        DependencyProperty.Register("ListToBind", typeof(IBindingList), typeof(CustomTextBlock), new PropertyMetadata(null, ListToBindPropertyChangedCallback));
    
      private static void ListToBindPropertyChangedCallback(DependencyObject o, DependencyPropertyChangedEventArgs e)
      {
        var customTextBlock = o as CustomTextBlock;
        if (customTextBlock != null && e.NewValue != e.OldValue) {
          var oldList = e.OldValue as IBindingList;
          if (oldList != null) {
            oldList.ListChanged -= customTextBlock.BindingListChanged;
          }
          var newList = e.NewValue as IBindingList;
          if (newList != null) {
            newList.ListChanged += customTextBlock.BindingListChanged;
          }
        }
      }
    
      private void BindingListChanged(object sender, ListChangedEventArgs e)
      {
        this.RaisePropertyChanged("ListToBind");
      }
    
      public IBindingList ListToBind
      {
        get { return (IBindingList)this.GetValue(ListToBindProperty); }
        set { this.SetValue(ListToBindProperty, value); }
      }
    
      private void RaisePropertyChanged(string propName)
      {
        var eh = this.PropertyChanged;
        if (eh != null) {
          eh(this, new PropertyChangedEventArgs(propName));
        }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
    }
    

    here is the usage for the CustomTextBlock (not tested)

    
    

    @Fueled hope this helps

提交回复
热议问题