如何在Silverlight MVVM中从View到ViewModel获取文本框值?

时间:2012-10-16 10:42:57

标签: silverlight mvvm

目前我正在使用带有MVVM的silverlight5。在SL5中,我需要做以下事情。 我在xaml(设计页面)中有3个文本框和1个按钮控件和i datagrid。

这是设计视图(Xaml):

<UserControl.DataContext>
        <VC:EmployeeListViewModel />
    </UserControl.DataContext>
        <Grid x:Name="LayoutRoot">
        <my:DataGrid x:Name="McDataGrid" ItemsSource="{Binding Employees,UpdateSourceTrigger=PropertyChanged}" Margin="130,151,0,0" Height="137" VerticalAlignment="Top" RowBackground="#AA5D9324" AutoGenerateColumns="True" HorizontalAlignment="Left" Width="193">
        </my:DataGrid>
        <Button Content="Show Message" Width="100" Height="25" Margin="256,75,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <si:CallDataMethod Method="AddEmployeeCommand"/>
                    <si:ShowMessageBox Caption="Thank you"
                                       Message="Thanks for trying the Example"
                                       MessageBoxButton="OK"/>
                    <si:SetProperty TargetName="LayoutRoot" 
            PropertyName="Background" Value="PaleGoldenrod"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
     <TextBlock FontWeight="Bold" Height="26" HorizontalAlignment="Left" Margin="47,12,0,0" Name="textBlock1" Text="First Name:" VerticalAlignment="Top" Width="77" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="130,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Employee.Fname}" />
        <TextBlock FontWeight="Bold" Height="25" HorizontalAlignment="Left" Margin="35,44,0,0" Name="textBlock2" Text="Second Name:" VerticalAlignment="Top" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="130,44,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" />
        <TextBlock FontWeight="Bold" Height="23" HorizontalAlignment="Left" Margin="45,75,0,0" Name="textBlock3" Text="Department:" VerticalAlignment="Top" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="130,75,0,0" Name="textBox3" VerticalAlignment="Top" Width="120" />
        <!-- Add reference to Microsoft.Expression.Interactions.dll, System.Windows.Interactivity.dll -->
            <!-- Use mvvmxmlns snippet to add i and ei namespace prefixes -->
       </ComboBox> 
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="64,122,0,0" Name="textBlock4" Text="Choose:" VerticalAlignment="Top" FontWeight="Bold" />
</Grid>
</UserControl>

在同一个项目中,我创建了一个名为“ViewModel”的文件夹: 在同一文件夹中,我添加了一个名为EmployeeListViewModel.cs

的类文件

我的问题是这个。如何将文本框值传递给viewmodel [EmployeeListViewModel]并将其插入Datagrid。

EmployeeListViewModel.cs:

public class EmployeeListViewModel:INotifyPropertyChanged 
    {
        public ObservableCollection<Employee> Employees { get; private set; }

        public EmployeeListViewModel()
        {
            Employees = Silverlight_MVVM.DataHelper.EmployeeDataHelper.EmployeeData ();
        }

        private Employee _SelectedEmployee;
        public Employee SelectedEmployee
        {
            get
            {
                return _SelectedEmployee;
            }
            set
            {
                _SelectedEmployee = value;
                RaisePropertyChanged("SelectedEmployee");
            }
        }

        private Employee _Names;
        public Employee Names
        {
            get
            {
                return _Names;
            }
            set
            {
                _Names = value;
                RaisePropertyChanged("Names");
            }
        }

        public void HandleShowMessage()
        {
           // MessageBox.Show("Hello " + Names + ",Welcome to EventTrigger for MVVM.");

        }
        public RelayCommand _AddEmployeeCommand;
        /// <summary>
        /// Returns a command that show the customer.
        /// </summary>
        public ICommand AddEmployeeCommand
        {
            get
            {
                if (_AddEmployeeCommand == null)
                {
                    _AddEmployeeCommand = new RelayCommand(
                        param => this.AddEmployee(),
                        param => this.CanAddEmployee
                        );
                }
                return _AddEmployeeCommand;
            }
        }

        public bool CanAddEmployee
        {
            get
            {
                 return true;
            }
        }

        public void AddEmployee()
        {
            //Employee newEmployee = new Employee("New1);
            Employee newEmployee = new Employee() **{};**
           --> **Here i have to pass the value.. How is it possible..?**
            Employees.Add(newEmployee);
            SelectedEmployee = newEmployee;
        }



        #region INotifyPropertyChanged
        // [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
}

3 个答案:

答案 0 :(得分:1)

您必须使用TwoWay绑定模式。例如,Text="{Binding Path=Employee.Fname,Mode=TwoWay}"。您可以阅读有关Binding.Mode on MSDN的更多信息。

答案 1 :(得分:1)

不是100%确定你是怎么回事? 通常我会将网格绑定到所选的员工,然后将文本框的值绑定到selectedemployee上的属性。当您更改行时,这些将更新以反映网格中当前所选行的值。 那么你添加一个新的空白员工,它将具有空白值,直到它们被输入文本框。当然,您需要构建一些验证,以确保不会添加大量的blabnk行。

如果我理解你想要如何做到这一点,那么正如文本框中的值与所选行无关,但仅用于添加具有这些值的新员工?为了实现这一点,我建议将Textbox绑定到Viewmodel上的字符串值。目前,您将它们绑定到看似实际不存在的内容。相反,我会在视图模型上将它们绑定到自己的属性:

private string _employeeFirstName; 
    public string EmployeeFirstName 
    { 
        get 
        { 
            return _employeeFirstName; 
        } 
        set 
        { 
            _employeeFirstName= value; 
            RaisePropertyChanged("EmployeeFirstName"); 
        } 
    } 

然后在xaml绑定到该属性 - 使用Mode = TwoWay,以便viewmodel也接收任何更新

<TextBox Height="23" HorizontalAlignment="Left" Margin="130,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=EmployeeFirstName, Mode=TwoWay}" />

然后在创建新员工时:

    public void AddEmployee()    
    {     
        Employee newEmployee = new Employee() {FName = this.EmployeeFirstName};    

        Employees.Add(newEmployee);    
        SelectedEmployee = newEmployee;    
    } 

答案 2 :(得分:0)

我在View Model中创建了三个名为Fname,Sname,Dept的属性。

private string _fname;
        public string Fname
        {
            get
            {
                return _fname;
            }
            set
            {
                _fname = value;
                RaisePropertyChanged("Fname");
            }
        }

功能如下..

public void AddEmployee()    
    {     
        Employee newEmployee = new Employee() {Fname=this.Fname;Sname=this.Sname;Dept=this.Dept};    

        Employees.Add(newEmployee);    
        SelectedEmployee = newEmployee;    
    } 

效果很好..

设计代码是:

<TextBlock FontWeight="Bold" Height="26" HorizontalAlignment="Left" Margin="47,12,0,0" Name="textBlock1" Text="First Name:" VerticalAlignment="Top" Width="77" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="130,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Fname,Mode=TwoWay}" />
        <TextBlock FontWeight="Bold" Height="25" HorizontalAlignment="Left" Margin="35,44,0,0" Name="textBlock2" Text="Second Name:" VerticalAlignment="Top" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="130,44,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" Text="{Binding Path=Sname,Mode=TwoWay}"/>
        <TextBlock FontWeight="Bold" Height="23" HorizontalAlignment="Left" Margin="45,75,0,0" Name="textBlock3" Text="Department:" VerticalAlignment="Top" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="130,75,0,0" Name="textBox3" VerticalAlignment="Top" Width="120"  Text="{Binding Path=Dept,Mode=TwoWay}"/>

<Button Content="Show Message" Width="100" Height="25" Margin="256,75,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <si:CallDataMethod Method="AddEmployee"/>
                    <si:ShowMessageBox Caption="Thank you"
                                       Message="Thanks for trying the Example"
                                       MessageBoxButton="OK"/>
                    <si:SetProperty TargetName="LayoutRoot" 
            PropertyName="Background" Value="PaleGoldenrod"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>

希望它对我们有用..