首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用List<string>绑定WPF文本块

使用List<string>绑定WPF文本块
EN

Stack Overflow用户
提问于 2008-12-05 22:26:32
回答 4查看 51.9K关注 0票数 15

有没有人知道有一种简单的方法来绑定一个文本块到一个列表。到目前为止,我所做的是创建一个列表视图并将其绑定到列表,然后在列表视图中创建一个使用单个文本块的模板。

我真正想做的是将列表绑定到一个文本块,并让它显示所有行。

在Winforms中有一个"Lines“属性,我可以直接将列表放入其中,但我在WPF textblock或TextBox中看不到它。

有什么想法吗?

我错过了什么简单的东西吗?

下面是代码

代码语言:javascript
运行
复制
<UserControl x:Class="QSTClient.Infrastructure.Library.Views.WorkItemLogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Width="500" Height="400">
<StackPanel>
    <ListView ItemsSource="{Binding Path=Logs}" >
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Log Message">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</StackPanel>

和WorkItem类

代码语言:javascript
运行
复制
public class WorkItem
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string CurrentLog { get; private set; }
    public string CurrentStatus { get; private set; }
    public WorkItemStatus Status { get; set; }
    public ThreadSafeObservableCollection<string> Logs{get;private set;}

我正在使用棱镜创建控件并将其放入WindowRegion中

代码语言:javascript
运行
复制
        WorkItemLogView newView = container.Resolve<WorkItemLogView>();
        newView.DataContext = workItem;
        regionManager.Regions["ShellWindowRegion"].Add(newView);

谢谢

EN

Stack Overflow用户

发布于 2011-11-09 16:20:07

如果你使用这个转换器,它在第一次就能完美地工作,但如果一个或多个日志记录出现在日志列表中,你的绑定就不会有更新,因为这个转换器只在第一次工作。所有不是item控件的控件都不订阅listchanged事件!

以下是此场景的一小段代码

代码语言:javascript
运行
复制
using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace BindListToTextBlock
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    private WorkItem workItem;

    public MainWindow() {
      this.WorkItems = new ObservableCollection<WorkItem>();
      this.DataContext = this;
      this.InitializeComponent();
    }

    public class WorkItem
    {
      public WorkItem() {
        this.Logs = new ObservableCollection<string>();
      }

      public string Name { get; set; }
      public ObservableCollection<string> Logs { get; private set; }
    }

    public ObservableCollection<WorkItem> 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));
      }
    }
  }
}

xaml

代码语言:javascript
运行
复制
<Window x:Class="BindListToTextBlock.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:BindListToTextBlock="clr-namespace:BindListToTextBlock"
        Title="MainWindow"
        Height="350"
        Width="525">
  <Grid>
    <Grid.Resources>
      <BindListToTextBlock:ListToStringConverter x:Key="ListToStringConverter" />
    </Grid.Resources>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition />
    </Grid.RowDefinitions>
    <Button Grid.Row="0"
            Content="Add item..."
            Click="Button_Click" />
    <Button Grid.Row="1"
            Content="Add some log to last item"
            Click="Button_Click_1" />
    <ListView Grid.Row="2"
              ItemsSource="{Binding Path=WorkItems}">
      <ListView.View>
        <GridView>
          <GridViewColumn Header="Name">
            <GridViewColumn.CellTemplate>
              <DataTemplate>
                <TextBlock Text="{Binding Path=Name}" />
              </DataTemplate>
            </GridViewColumn.CellTemplate>
          </GridViewColumn>
          <GridViewColumn Header="Log Message">
            <GridViewColumn.CellTemplate>
              <DataTemplate>
                <TextBlock Text="{Binding Path=Logs, Converter={StaticResource ListToStringConverter}}" />
              </DataTemplate>
            </GridViewColumn.CellTemplate>
          </GridViewColumn>
        </GridView>
      </ListView.View>
    </ListView>
  </Grid>
</Window>

转换器

代码语言:javascript
运行
复制
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<string>().ToArray());
      }
      return "no messages yet";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
      return DependencyProperty.UnsetValue;
    }
  }
}

编辑

这里有一个更新问题的快速解决方案(这也可以通过附加属性实现)

代码语言:javascript
运行
复制
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;
}

下面是CustomTextBlock的用法(未经过测试)

代码语言:javascript
运行
复制
<TextBlock Text="{Binding Path=ListToBind, RelativeSource=Self, Converter={StaticResource ListToStringConverter}}"
           ListToBind={Binding Path=Logs} />

@燃起希望,这很有帮助

票数 5
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/345385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档