Binding ObservableCollection<> to a TextBox

蹲街弑〆低调 提交于 2019-12-01 15:49:00

Is this because the Text binding simple does not handle the change events of the collection?

Indeed. A binding updates only when its source property changes. If you change the TextLines property by setting a whole new ObservableCollection and implement INotifyPropertyChanged, your binding will work as expected. Adding new elements to the collection will have meaning only if it's bound to a property like ItemsControl.ItemsSource that listens to the collection changes.

One option would of course be for me to handle the collection changes and propogate those to a Text property that the TextBox is bound to, which is fine.

That would be another solution.

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.

<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>

And the converter:

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();
    }
}

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.

update below code

  private void Button_Click(object sender, RoutedEventArgs e)
    {
        TextLines.Add("Line :" + TextLines.Count);
      BindingExpression be =  BindingOperations.GetBindingExpression(txtName, TextBox.TextProperty);
      be.UpdateTarget();
    } 

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.

public string TextLines {get;set;}

 <TextBox Text="{Binding TextLines, Mode=OneWay/> 

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!