繁体   English   中英

MVVM WPF 将新项目从绑定到 Model class 的嵌套属性的文本框中添加到 DataGrid

[英]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的嵌套属性。

最后,我知道我的问题与这个问题非常相似,但我遵循了那里的建议并尝试匹配他们的解决方案,但不知何故我无法让它发挥作用。 谢谢!

编辑:在按下“添加”按钮后添加了一些之前 - 之后的 DataGrid 图片: 在此处输入图像描述 在此处输入图像描述

我试图复制你的问题,但我不得不删除 styles 因为你没有提供它们。 它在我身边有效,所以问题可能出在风格上?

在此处输入图像描述

请删除文本框(ParameterTextbox)的styles,然后看看它是否有效。 如果你能给我提供样式的源代码,我可以看一下。 也许您正在覆盖 text 属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM