![](/img/trans.png)
[英]how to add text from textboxes and add it to datagrid using MVVM Wpf
[英]MVVM WPF Add new item to the DataGrid from Textboxes which are bound to the nested properties of the Model class
我是 WPF 和 MVVM 模式的新手,我尝试创建一个简单的 WPF 项目来查询 I 型钢型材数据库并通过 DataGrid 向用户显示。 成功完成后,我现在进入下一部分:让用户通过填写一组 TextBox 将新的钢型材添加到 DataGrid。
Model
namespace SectionGuardWPF.MVVM.Model
{
public class IProfileModel : ObservableObject
{
#region Private Fields
public short _recno;
public string _name;
public string _staadName;
public double _ax;
public double _d;
public double _bf;
public double _tf;
public double _tw;
public double _iz;
public double _ix;
public double _ct;
public double _iy;
public double _zx;
public double _zy;
#endregion
#region Public Properties
/// <summary>
/// Properties are given NotifyPropertyChanged method to allow for a change in property to be notified
/// </summary>
public short RECNO
{
get { return _recno; }
set
{
_recno = value;
OnPropertyChanged();
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
...
// Repeated for the other fields
ObservableObject:实现INotifyPropertyChanged
的基础 class
namespace SectionGuardWPF.Core
{
public class ObservableObject : INotifyPropertyChanged
{
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
protected void OnPropertyChanged([CallerMemberName] string name = null) // If you use the CallerMemberName attribute, calls to the NotifyPropertyChanged method don't have to specify the property name as a string argument
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
中继命令
namespace SectionGuardWPF.Core
{
class RelayCommand : ICommand
{
private Action<object> _execute;
private Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object,bool> canExecute=null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
查看 Model
namespace SectionGuardWPF.MVVM.ViewModel
{
public class IProfilesViewModel:ObservableObject
{
#region Private Fields
private readonly string _connectionString = //Hidden
private ObservableCollection<IProfileModel> _iProfiles;
private ICommand _getIProfilesCommand;
private ICommand _addNewIProfileCommand;
private IProfileModel _iProfile = new IProfileModel();
#endregion
#region Constructor
public IProfilesViewModel()
{
// Set default Profile Database for the DataGrid upon View instantiation
IProfiles = GetIProfiles();
}
#endregion
#region Public Properties and Commands
/// <summary>
/// Public properties of the IProfilesViewModel Class (used for view binding with IProfilesSubView)
/// </summary>
public ObservableCollection<IProfileModel> IProfiles
{
get { return _iProfiles; }
set
{
_iProfiles = value;
OnPropertyChanged();
}
}
public IProfileModel IProfile
{
get { return _iProfile; }
set
{
_iProfile = value;
OnPropertyChanged();
}
}
public ICommand GetIProfilesCommand
{
get
{
if (_getIProfilesCommand == null)
{
_getIProfilesCommand = new RelayCommand(
param => GetIProfiles()
);
}
return _getIProfilesCommand;
}
}
public ICommand AddNewIProfileCommand
{
get
{
if (_addNewIProfileCommand == null)
{
_addNewIProfileCommand = new RelayCommand(
param => AddNewIProfile()
);
}
return _addNewIProfileCommand;
}
}
#endregion
#region Private Methods
private ObservableCollection<IProfileModel> GetIProfiles()
{
TableDataProvider tableDataProvider = new TableDataProvider(_connectionString);
tableDataProvider.QueryString = "SELECT * FROM [I Shape]";
IEnumerable<IProfileModel> iProfiles = tableDataProvider.Query<IProfileModel>();
ObservableCollection<IProfileModel> iProfileObsvCol = new ObservableCollection<IProfileModel>(iProfiles);
return iProfileObsvCol;
}
private void AddNewIProfile()
{
IProfiles.Add(
new IProfileModel
{
RECNO = IProfile.RECNO,
Name = IProfile.Name,
StaadName = IProfile.StaadName,
AX = IProfile.AX,
D = IProfile.D,
Bf = IProfile.Bf,
Tf = IProfile.Tf,
Tw = IProfile.Tw,
Ix = IProfile.Ix,
Iy = IProfile.Iy,
Iz = IProfile.Iz,
Ct = IProfile.Ct,
Zx = IProfile.Zx,
Zy = IProfile.Zy
}
);
}
#endregion
}
}
看法
<UserControl x:Class="SectionGuardWPF.MVVM.View.IProfilesSubView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SectionGuardWPF.MVVM.View"
xmlns:viewModel= "clr-namespace:SectionGuardWPF.MVVM.ViewModel"
xmlns:view="clr-namespace:SectionGuardWPF.MVVM.View"
mc:Ignorable="d"
d:DesignHeight="580" d:DesignWidth="1300">
<UserControl.DataContext>
<viewModel:IProfilesViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="620"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<DataGrid x:Name="ProfilesDataGrid"
x:FieldModifier="public"
ItemsSource="{Binding IProfiles, Mode=TwoWay}">
</DataGrid>
<Border Grid.Column="1"
CornerRadius="20"
Background ="White"
Margin="10">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
<RowDefinition Height="150"/>
</Grid.RowDefinitions>
<TextBlock Text="I-Profiles Data Viewer"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="Black"
FontSize="22"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="RECNO"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="0"
FontSize="14"/>
<TextBox x:Name="RECNOTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="0"
Text="{Binding IProfile.RECNO, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Name"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="1"
FontSize="14"/>
<TextBox x:Name="NameTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="1"
Text="{Binding IProfile.Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="StaadName"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="2"
FontSize="14"/>
<TextBox x:Name="StaadNameTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="2"
Text="{Binding IProfile.StaadName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="AX"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="3"
FontSize="18"/>
<TextBox x:Name="AXTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="3"
Text="{Binding IProfile.AX, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="D"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="4"
FontSize="18"/>
<TextBox x:Name="DTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="4"
Text="{Binding IProfile.D, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Bf"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="5"
FontSize="18"/>
<TextBox x:Name="BfTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="5"
Text="{Binding IProfile.Bf, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Tf"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="0"
Grid.Row="6"
FontSize="18"/>
<TextBox x:Name="TfTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="0"
Grid.Row="6"
Text="{Binding IProfile.Tf, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Tw"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="0"
FontSize="18"/>
<TextBox x:Name="TwTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="0"
Text="{Binding IProfile.Tw, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Ix"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="1"
FontSize="18"/>
<TextBox x:Name="IxTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="1"
Text="{Binding IProfile.Ix, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Iy"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="2"
FontSize="18"/>
<TextBox x:Name="IyTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="2"
Text="{Binding IProfile.Iy, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Iz"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="3"
FontSize="18"/>
<TextBox x:Name="IzTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="3"
Text="{Binding IProfile.Iz, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Ct"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="4"
FontSize="18"/>
<TextBox x:Name="CtTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="4"
Text="{Binding IProfile.Ct, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Zx"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="5"
FontSize="18"/>
<TextBox x:Name="ZxTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="5"
Text="{Binding IProfile.Zx, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<TextBlock Text="Zy"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="20,0,0,0"
Foreground="#1A80FA"
Grid.Column="1"
Grid.Row="6"
FontSize="18"/>
<TextBox x:Name="ZyTextBox"
Margin="0,0,20,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Style="{StaticResource ParameterTextbox}"
Grid.Column="1"
Grid.Row="6"
Text="{Binding IProfile.Zy, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</Grid>
<StackPanel Grid.Row="2"
Orientation="Horizontal">
<Button x:Name="AddButton"
Style="{StaticResource AddButton}"
Content="Add"
Background="#28C941"
Height="50"
Width="150"
Margin="85,0,0,0"
Command="{Binding AddNewIProfileCommand}"/>
<Button x:Name="EditButton"
Style="{StaticResource AddButton}"
Content="Edit"
Background="#FFBD2E"
Height="50"
Width="150"
Margin="20,0,0,0"/>
<Button x:Name="DeleteButton"
Style="{StaticResource AddButton}"
Content="Delete"
Background="#FF6059"
Height="50"
Width="150"
Margin="20,0,0,0"/>
</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>
My Model class is a class called the IProfileModel
that represents the I-Shape Profiles, I have made so that it inherits from the ObservableObject
class so that it can use the NotifyPropertyChanged methods and I have made so that the properties of the Model class has implemented OnPropertyChanged()
方法。
在我的视图中,我已将 DataGrid 的源绑定到IProfiles
,这是一个存储IProfileModel
实例的ObservableCollection
。 每个 TextBox 对应于IProfileModel
class 的一个属性,因此每个 TextBox 的 Text 属性绑定到 ViewModel 的IProfile
属性的相应嵌套属性。 “添加”按钮绑定到 ViewModel 中的相应 ICommand,称为AddNewIProfileCommand
在我的 ViewModel 中,我使用名称IProfile
添加了IProfileModel
作为其属性之一,TextBox.Text 属性绑定到 IProfile 的嵌套属性,如视图的IProfile
所示。 至于AddNewIProfileCommand
,我已经使它对应于一个名为 AddNewIProfile() 的私有方法,该方法将添加一个新的IProfileModel
object ,其属性将引用绑定到文本框的IProfile
属性的嵌套属性。
编辑:我想补充一点, AddNewIProfile()
会将新的IProfileModel
object 添加到绑定到 DataGrid 的IProfiles
我的主要问题是,每当我修改文本框然后单击按钮将配置文件添加到 DataGrid 时,新添加到 DataGrid 的条目始终是具有空属性值的IProfileModel
(IProfileModel 的所有字符串属性都是IProfileModel
和所有数值类型属性为 0)。 即使我已将UpdateSourceTrigger
设置为PropertyChanged
并将Mode
设置为Two Way
并且IProfile
本身属于从ObservableObject
class 继承的IProfileModel
class,但修改 TextBoxes 似乎不会更改IProfile
的嵌套属性。
最后,我知道我的问题与这个问题非常相似,但我遵循了那里的建议并尝试匹配他们的解决方案,但不知何故我无法让它发挥作用。 谢谢!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.