绑定 ObservableCollection<>到文本框
我有以 ObservableCollection
形式从 Web 服务返回的数据,我想将集合绑定到只读 TextBox
,以便用户可以选择和将数据复制到剪贴板。
为了将集合绑定到 TextBox 的 Text 属性,我创建了 IValueConverter
,它将集合转换为文本字符串。这似乎有效,只是它只能工作一次,就好像绑定无法识别 Observable 集合的后续更改。这是一个重现问题的简单应用程序,只是为了确认绑定正常工作,我还绑定到“ListBox”,
这是因为简单的文本绑定不处理集合的更改事件吗?
当然,一种选择是我处理集合更改并将这些更改传播到 TextBox 绑定到的 Text 属性,这很好,但我想了解为什么在我看来显而易见的解决方案不起作用正如预期的那样。
XAML
<Window x:Class="WpfTextBoxBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTextBoxBinding"
Title="MainWindow" Height="331" Width="402">
<StackPanel>
<StackPanel.Resources>
<local:EnumarableToTextConverter x:Key="EnumarableToTextConverter" />
</StackPanel.Resources>
<TextBox Text="{Binding TextLines, Mode=OneWay, Converter={StaticResource EnumarableToTextConverter}}" Height="100" />
<ListBox ItemsSource="{Binding TextLines}" Height="100" />
<Button Click="Button_Click" Content="Add Line" />
</StackPanel >
</Window>
代码隐藏
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Globalization;
namespace WpfTextBoxBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableCollection<string> TextLines {get;set;}
public MainWindow()
{
DataContext = this;
TextLines = new ObservableCollection<string>();
// Add some initial data, this shows that the
// TextBox binding works the first time
TextLines.Add("First Line");
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
TextLines.Add("Line :" + TextLines.Count);
}
}
public class EnumarableToTextConverter : IValueConverter
{
public object Convert(
object value, Type targetType,
object parameter, CultureInfo culture)
{
if (value is IEnumerable)
{
StringBuilder sb = new StringBuilder();
foreach (var s in value as IEnumerable)
{
sb.AppendLine(s.ToString());
}
return sb.ToString();
}
return string.Empty;
}
public object ConvertBack(
object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实现此目的的一种稍微优雅的方法是在 Text 属性上使用 MultiBinding 并绑定到 Collection 的 Count 属性。这将在每次集合的计数发生变化时更新绑定,并根据您定义的 MultiValueConverter 更新文本。
和转换器:
在我的用例中,我不允许 TextBox 更新其源(因此“Mode =“OneWay””),但如果需要,转换器的 ConvertBack 方法将处理该问题。
A slightly more elegant way to achieve that is to use MultiBinding on the Text property and bind to the Collection's Count property. This will update the binding every time the collection's Count changes and update the Text according to a MultiValueConverter you define.
And the converter:
In my use case, I don't allow the TextBox to update its source (hence the ´Mode="OneWay"´), but if need be the Converter's ConvertBack method would handle that.
的确。仅当其源属性发生更改时,绑定才会更新。如果您通过设置全新的
ObservableCollection
来更改TextLines
属性并实现INotifyPropertyChanged
,您的绑定将按预期工作。仅当将新元素绑定到像ItemsControl.ItemsSource
这样侦听集合更改的属性时,向集合添加新元素才有意义。那将是另一种解决方案。
Indeed. A binding updates only when its source property changes. If you change the
TextLines
property by setting a whole newObservableCollection
and implementINotifyPropertyChanged
, your binding will work as expected. Adding new elements to the collection will have meaning only if it's bound to a property likeItemsControl.ItemsSource
that listens to the collection changes.That would be another solution.
更新下面的代码
,其中 txtName 是您的文本框的名称
MVVM 方式
1- 在 ViewModel 中定义一个字符串类型的属性,如下所示,并将该属性绑定到如下所示的文本框文本属性 a 并删除 ValueConverter no现在需要。
2-我认为,您最有可能使用命令处理程序处理按钮单击事件,说您的命令是 AddMoreLines
,因此在 AddMoreLine 命令处理程序中,在 OBservrableCollection 中添加新对象后,创建一个 StringBuilder 并附加 Collection 的所有内容并分配步骤 1 中创建的属性的字符串。
3- 调用 PropertyChanged 处理程序。
update below code
where txtName is your name of your textbox
MVVM way
1- Difine a property of type string in your ViewModel as shown below and bind this property to the textbox text property a shown below and remove ValueConverter no need now.
2- I think , you most probably handling button click event using a Command Handler say your Command is AddMoreLines
so in the AddMoreLine Command Handler , after adding a new object in your OBservrableCollection , create a StringBuilder and append all the content of your Collection and assign the string to the property created in step 1.
3- Call PropertyChanged Handler.