将用户输入从TextBoxes绑定到对象集合,并通过MVVM中的ComboBox进行填充

时间:2015-02-13 14:19:39

标签: c# wpf xaml mvvm combobox

我是WPF和MVVM的新手,但到目前为止,我无法找到这种双向绑定方案的方法。我还应该提一下,这不是一个学校项目,而是我自己有兴趣学习MVVM的不同方面。

我的视图包含一个带有TextBox的窗口,用于收集用户输入(SchoolName,SchoolAddress,SchoolTelephone等)。 View还有一个Add按钮,可以保存TextBoxes的输入,创建一个School对象,然后填充一个ComboBox(带有学校名称)。因此,每次用户单击“添加”按钮时,ComboBox列表中都会显示一个新的学校,并且所有TextBox都会重置并准备好进行新学校输入。我希望保留的另一个条件是,您可以将TextBoxes与ComboBox中的选定项目进行双向绑定。因此,当您从列表中选择学校时,TextBox会填充其对象的信息,并且可以进一步编辑。

我设法获得的是我将TextBox绑定到属性,我将ComboBox ItemsSource与学校的ObservableCollection绑定,SelectedItem绑定到SelectedSchool属性并且我已经将我的添加按钮绑定到AddSchoolCommand,这样就可以填充该集合。

我无法实现的是找到一种绑定SelectedSchool属性的方法,这样我就可以通过ComboBox项目列表修改现有的School对象,以及每次添加新学校时以某种方式从清除的TextBox开始。 TextBoxes既可以作为输入收集器,也可以显示现有的School数据。

所以这是我的方法:

// ViewModelBase

    internal void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
    }
    public event PropertyChangedEventHandler PropertyChanged; 

// ViewModel:

 public ObservableCollection<School> Schools { get; set; }
 public RelayCommand AddSchoolCommand { get; set; }

 string _SchoolName;
     public string SchoolName
            {
                get
                {
                    return _SchoolName;
                }
                set
                {
                    if (_SchoolName != value)
                    {
                        _SchoolName = value;
                        RaisePropertyChanged("SchoolName");
                    }
                }
            }

    string _SchoolAddress;
     public string SchoolAddress
            {
                get
                {
                    return _SchoolName;
                }
                set
                {
                    if (_SchoolAddress != value)
                    {
                        _SchoolAddress = value;
                        RaisePropertyChanged("SchoolAddress");
                    }
                }
            }

    string _SchooTelephone;
     public string SchooTelephone
            {
                get
                {
                    return _SchooTelephone;
                }
                set
                {
                    if (_SchooTelephone != value)
                    {
                        _SchoolAddress = value;
                        RaisePropertyChanged("SchooTelephone");
                    }
                }
            }

    object _SelectedSchool;
    public object SelectedSchool
    {
        get
        {
            return _SelectedSchool;
        }
        set
        {
            if (_SelectedSchool != value)
            {
                _SelectedSchool = value;
                RaisePropertyChanged("SelectedSchool");
            }
        }
    }

    public ViewModelResume()
    {
       Schools = new ObservableCollection<School>();
       AddSchoolCommand = new RelayCommand(AddSchool);
    }

    void AddSchool(Object obj)
    {
        Schools.Add(new School
        {
            Name = SchoolName,
            Address = SchoolAddress,
            Telephone = SchoolTelephone,
        });
    }

// XAML

<Grid Width="358" Height="135">
<TextBox x:Name="schoolName" Controls:TextBoxHelper.Watermark="School Name" Controls:TextBoxHelper.ClearTextButton="True" HorizontalAlignment="Left" Height="26" Margin="10,9,0,0" VerticalAlignment="Top" Width="166" Text="{Binding SchoolName, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="schoolAddress" Controls:TextBoxHelper.Watermark="School Address" Controls:TextBoxHelper.ClearTextButton="True" Height="26" Margin="0,9,10,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="167" Text="{Binding School Address, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="schoolTelephone" Controls:TextBoxHelper.Watermark="School Telephone" Controls:TextBoxHelper.ClearTextButton="True" HorizontalAlignment="Left" Height="26" Margin="10,79,0,0" VerticalAlignment="Top" Width="133" Text="{Binding SchoolTelephone, UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox x:Name="schoolsList" Text="Schools List" HorizontalAlignment="Left" Margin="10,155,0,0" VerticalAlignment="Top" Width="268" ToolTip="List of attended schools" IsEditable="True" IsReadOnly="True" ItemsSource="{Binding Schools}" SelectedItem="{Binding SelectedSchool}" DisplayMemberPath="SchoolName" />
<Button x:Name="saveSchoolButton" Content="Add" Margin="318,155,10,0" VerticalAlignment="Top" Height="26" Command="{Binding AddSchoolCommand}"/>
</Grid>

2 个答案:

答案 0 :(得分:2)

您的文本框正在侦听视图模型中的属性,这些属性不知道selectedSchool。 您可以将文本框绑定到selectedSchool.Properties

首先制作您所选择的Type School类型学校并按此启动

School _SelectedSchool = new School();

然后更改所有文本框以绑定到选定的学校属性

<TextBox Text="{Binding SelectedSchool.SchoolName, UpdateSourceTrigger=PropertyChanged}"/>

然后添加

void AddSchool(Object obj)
{
    Schools.Add(SelectedSchool);
    SelectedSchool = New School();

}

答案 1 :(得分:1)

@Muds的回答可能是做你想做的最好的方式。我在这里留下我的答案只是为了说明另一种方法。


首先,您应该将SelectedSchool属性的类型更改为School,而不是对象。然后,在其属性设置器中,根据选择设置SchoolNameSchoolAddressSchooTelephone(错字?)属性:

SchoolName = _SelectedSchool.Name;
// etc...

这意味着当您更改组合框中的选择时,所选学校的详细信息将被传输到文本框。

AddSchool方法中,将新学校添加到列表后,只需清除绑定到文本框的属性:

SchoolName = String.Empty;
// etc...

使用相同按钮添加和编辑学校详细信息的想法在没有一点额外工作的情况下是不可行的。每个学校都需要一个唯一的标识符:这样,当您点击&#34;添加或编辑&#34;按钮,您可以查看学校列表,看看该学校是否已经存在。如果是,那么它就是一个编辑,否则它就是一所新学校。

您的问题是您没有唯一标识符。您无法使用学校名称,因为这可能会在编辑期间发生变化。尝试向School对象添加另一个属性以用作标识符,类似于int会做的事情(您不必向用户显示此值)。然后,当您创建一所新学校时,创建一个新的独特学校ID&#34;编号并将其分配给该学校。