wpf - 将 ObservableCollection<> 绑定(bind)到 TextBox

标签 wpf silverlight data-binding ivalueconverter

我有以 ObservableCollection<string> 形式从 Web 服务返回的数据我想将集合绑定(bind)到只读 TextBox以便用户可以选择数据并将其复制到剪贴板。

为了使集合绑定(bind)到我创建的 TextBox 的 Text 属性 IValueConverter它将集合转换为文本字符串。这似乎有效,只是它只有效一次,就好像绑定(bind)无法识别对 Observable 集合的后续更改。这是一个重现问题的简单应用程序,只是为了确认绑定(bind)正常工作,我还绑定(bind)到“ListBox”

这是因为 Text binding simple 不处理集合的更改事件吗?

一种选择当然是让我处理集合更改并将这些更改传播到 TextBox 绑定(bind)的 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();
    }
  }
}

最佳答案

一种更优雅的实现方式是在 Text 属性上使用 MultiBinding 并绑定(bind)到 Collection 的 Count 属性。这将在每次集合的 Count 更改时更新绑定(bind),并根据您定义的 MultiValueConverter 更新 Text。

<TextBox>
    <TextBox.Text>
        <MultiBinding Converter="{x:Static l:Converters.LogEntryCollectionToTextConverter}">
            <Binding Path="LogEntries" Mode="OneWay"/>
            <Binding Path="LogEntries.Count" Mode="OneWay" />
        </MultiBinding>
    </TextBox.Text>
</TextBox>

和转换器:
public static class Converters
{
    public static LogEntryCollectionToTextConverter LogEntryCollectionToTextConverter = new LogEntryCollectionToTextConverter();
}

public class LogEntryCollectionToTextConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableCollection<LogEntry> logEntries = values[0] as ObservableCollection<LogEntry>;

        if (logEntries != null && logEntries.Count > 0)
            return logEntries.ToString();
        else
            return String.Empty;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在我的用例中,我不允许 TextBox 更新其源(因此是“Mode="OneWay"”),但如果需要,转换器的 ConvertBack 方法会处理它。

关于wpf - 将 ObservableCollection<> 绑定(bind)到 TextBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4353186/

相关文章:

wpf - 将图像转换为 XAML?

c# - 用于绑定(bind)的 Xamarin.Forms MarkupExtension

wpf - WPF 应用程序中的 IIS 平滑流式处理

c# - 改变 parent 的风格

c# - 数据绑定(bind)到数据绑定(bind)对象内的列表

wpf - 如何在 XAML 中将 DependencyProperty 重置回默认值

visual-studio-2010 - Microsoft UITesting自动化引擎信息

c# - SourceUpdated 和 NotifyOnSourceUpdated 未在 ListBox 中触发

.net - 为什么这个数据绑定(bind)不起作用?

c# - 当我们尝试将 Snoop for WPF 附加到我们的应用程序时,为什么它会崩溃?