10

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

这是模型类的代码:

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

任何人都可以建议我是否以正确的方式进行此操作?

4

3 回答 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}" />

在你的绑定中。

于 2009-06-30T07:44:27.113 回答
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>
于 2009-06-30T07:44:39.173 回答
0

xml视图:

<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

于 2020-01-14T06:42:46.697 回答