簡體   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