![](/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.