有没有人知道是否有一种简单的方法将文本块绑定到List。 到目前为止我所做的是创建一个listview并将其绑定到List,然后我在listview中有一个使用单个文本块的模板。
我真正想要做的就是将List绑定到一个文本块并让它显示所有行。
在Winforms中有一个“Lines”属性,我可以将List放入,但我没有在WPF文本块或TextBox上看到它。
有什么想法吗?
我想念一些简单的事吗?
这是代码
<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类
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;}
我正在使用Prism创建控件并将其放入WindowRegion
WorkItemLogView newView = container.Resolve<WorkItemLogView>();
newView.DataContext = workItem;
regionManager.Regions["ShellWindowRegion"].Add(newView);
感谢
答案 0 :(得分:32)
将List转换为单个字符串,其中“\ r \ n”作为其间的分隔符。并将其绑定到TextBlock。确保TextBlock的高度不受限制,以便它可以根据行数增长。 我将它实现为XAML Binding的值转换器,它将字符串列表转换为单个字符串,并在其间添加新行
<TextBlock Text="{Binding Path=Logs,Converter={StaticResource ListToStringConverter}}"/>
ListToStringConverter看起来像这样:
[ValueConversion(typeof(List<string>), typeof(string))]
public class ListToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (targetType != typeof(string))
throw new InvalidOperationException("The target must be a String");
return String.Join(", ", ((List<string>)value).ToArray());
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
答案 1 :(得分:4)
如果您使用转换器,它首次完美工作, 但是如果一个或多个日志记录进入日志记录列表,则绑定没有更新,因为转换器仅在第一次运行时才起作用。 所有没有项控件的控件都不会订阅listchanged事件!
这是一个针对此场景的小代码
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
<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>
转换器
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;
}
}
}
修改强>
这是更新propblem的快速解决方案(也可以使用附加属性)
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
(未测试)
<TextBlock Text="{Binding Path=ListToBind, RelativeSource=Self, Converter={StaticResource ListToStringConverter}}"
ListToBind={Binding Path=Logs} />
@Fueled希望这会有所帮助
答案 2 :(得分:2)
我会无耻地发布一个链接,回答我对一个非常相似的问题的回答:Binding ObservableCollection<> to a TextBox。
就像punker76所说,如果你将Text绑定到一个集合,它将在你设置集合时更新,但是当集合发生变化时不会更新。此链接演示了punker76解决方案的替代方案(诀窍是多次绑定到集合的计数)。
答案 3 :(得分:0)
对于concat集合对象:
/// <summary>Convertisseur pour concaténer des objets.</summary>
[ValueConversion(typeof(IEnumerable<object>), typeof(object))]
public class ConvListToString : IValueConverter {
/// <summary>Convertisseur pour le Get.</summary>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
return String.Join(", ", ((IEnumerable<object>)value).ToArray());
}
/// <summary>Convertisseur inverse, pour le Set (Binding).</summary>
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
Juste想要覆盖你对象的ToString()。