How can I bind an ObservableCollection to TextBoxes in a DataTemplate? How can I bind an ObservableCollection to TextBoxes in a DataTemplate? wpf wpf

How can I bind an ObservableCollection to TextBoxes in a DataTemplate?


You need a property to bind two way, so string is not good for this.

Wrap it in a string object, like this:

public class Model{    public ObservableCollection<StringObject> List { get; private set; }    public Model()    {        List = new ObservableCollection<StringObject>                   {                       new StringObject {Value = "why"},                       new StringObject {Value = "not"},                       new StringObject {Value = "these"},                   };    }}public class StringObject{    public string Value { get; set; }}

and bind to Value property instead of "."

Also, you don't need to notify of a change in observable collection, so until your model has some other propertis of its own, it does not need to have INotifyPropertyChange. If you want your ItemsControl react to changes in the individual StringObjects, then you should add INotifyPropertyChanged to a StringObject.

And yet again, two way binding is default, so you need only

<TextBox Text="{Binding Path=Value}" />

in your binding.


I believe you need to derive your collection items from DependencyObject for TwoWay binding to work. Something like:

public class DependencyString: DependencyObject {    public string Value {        get { return (string)GetValue(ValueProperty); }        set { SetValue(ValueProperty, value); }    }    public static readonly DependencyProperty ValueProperty =        DependencyProperty.Register("Value", typeof(string), typeof(DependencyString), new UIPropertyMetadata(""));    public override string ToString() {        return Value;    }    public DependencyString(string s) {        this.Value = s;    }}public class Model {    private ObservableCollection<DependencyString> _list = new ObservableCollection<DependencyString>();    public ObservableCollection<DependencyString> List {        get { return _list; }    }    public Model() {         List.Add(new DependencyString("why"));         List.Add(new DependencyString("not"));        List.Add(new DependencyString("these?"));    }}

...

<StackPanel x:Name="theGrid">    <GroupBox BorderBrush="LightGreen">        <GroupBox.Header>            <TextBlock Text="Group" />                </GroupBox.Header>        <ItemsControl ItemsSource="{Binding Path=List}">            <ItemsControl.ItemTemplate>                <DataTemplate>                    <TextBox Text="{Binding Path=Value, Mode=TwoWay}"/>                </DataTemplate>            </ItemsControl.ItemTemplate>        </ItemsControl>    </GroupBox></StackPanel>


xaml view:

<ItemsControl ItemsSource="{Binding List}">    <ItemsControl.ItemTemplate>        <DataTemplate>            <TextBox Text="{Binding Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />        </DataTemplate>    </ItemsControl.ItemTemplate></ItemsControl>

in code behind in the constructor:

DataContext = new ViewModel();

in ViewModel Class:

class ViewModel : INotifyPropertyChanged    {        public event PropertyChangedEventHandler PropertyChanged;        private void NotifyPropertyChanged(string name)        {            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));        }        private ObservableCollection<StringObject> _List = new ObservableCollection<StringObject>();        public ObservableCollection<StringObject> List        {            get { return _List; }            set            {                _List = value;                NotifyPropertyChanged("List");            }        }        public ViewModel()        {            List = new ObservableCollection<StringObject>                {                    new StringObject {Value = "why"},                    new StringObject {Value = "not"},                    new StringObject {Value = "these"}                };        }    }    public class StringObject    {        public string Value { get; set; }    }

Be careful with a collection with type string it doesn't work, you have to use an object => StringObject