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

对着背影说爱祢 提交于 2019-11-30 03:49:32

问题


I am trying to successfully TwoWay bind an ObservableCollection to TextBoxes in a DataTemplate. I can get the data to display properly, but I am unable to change the list data through the UI. I have a Model class named 'model' which contains an ObservableCollection named 'List'. The class implements the INotifyPropertyChanged interface. Here is the xaml for the shell. The DataContext for Window1's grid is set to "theGrid.DataContext=model"

<Window x:Class="BindThat.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindThat"
Title="Window1" Height="300" Width="300">
<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=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </GroupBox> 
</StackPanel>

This is the code for the Model class:

class Model : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    private ObservableCollection<string> _list = new ObservableCollection<string>();
    public ObservableCollection<string> List
    {
        get { return _list; }
        set 
        { 
            _list = value;
            NotifyPropertyChanged("List");
        }
    }

    public Model()
    {
        List.Add("why");
        List.Add("not");
        List.Add("these?");
    }
}

Could anyone advise if I am going about this the correct way?


回答1:


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.




回答2:


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>


来源:https://stackoverflow.com/questions/1062045/how-can-i-bind-an-observablecollection-to-textboxes-in-a-datatemplate

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