我如何将ObservableCollection绑定到DataTemplate中的文本框?

问题描述 投票:10回答:3

我正在尝试将TwoWay成功地将ObservableCollection绑定到DataTemplate中的TextBoxes。我可以正确显示数据,但是无法通过UI更改列表数据。我有一个名为“模型”的Model类,其中包含一个名为“ List”的ObservableCollection。该类实现INotifyPropertyChanged接口。这是外壳的xaml。 Window1的网格的DataContext设置为“ 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>

这是Model类的代码:

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?");
    }
}

任何人都可以建议我是否要采用正确的方法吗?

wpf binding datatemplate two-way-binding
3个回答
13
投票

您需要一个属性以两种方式绑定,所以字符串对此无效。

将其包装在字符串对象中,如下所示:

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

并绑定到Value属性,而不是“。”

而且,您不需要通知可观察集合的更改,因此,在模型拥有自己的其他属性之前,它不需要INotifyPropertyChange。如果要让ItemsControl对单个StringObjects中的更改做出反应,则应将InotifyPropertyChanged添加到StringObject。

同样,默认是双向绑定,所以只需要

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

在您的装订中。


1
投票

我相信您需要从DependencyObject派生您的收集项,以便TwoWay绑定起作用。类似于:

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>

0
投票

xaml视图:

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

在构造函数后面的代码中:

DataContext = new ViewModel();

在ViewModel类中:

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

请小心类型为string的集合,它不起作用,必须使用一个对象=> StringObject

© www.soinside.com 2019 - 2024. All rights reserved.