ObservableCollection is not update after DataGrid

2019-09-20 09:28发布

I am new in wpf and mvvm databinding. Now i am trying to make crud process with data gird. I have a problem to updateing process.I want to get update value after data grid cell updated by mvvm process.

Model

public class EmployeeType : INotifyPropertyChanged
    {
        string _EmpType;
        public string EmpType
        {
            get
            {
                return _EmpType;
            }
            set
            {
                if(_EmpType !=value)
                {
                    _EmpType = value;
                    RaisePropertyChange("EmpType");
                }
            }
        }

        string _EmpTypeDesc;
        public string EmpTypeDesc
        {
            get
            {
                return _EmpTypeDesc;
            }
            set
            {
                if(_EmpTypeDesc!=value)
                {
                    _EmpTypeDesc = value;
                    RaisePropertyChange("EmpTypeDesc");
                }
            }
        }

        bool _OTRounding;
        public bool OTRounding
        {
            get
            {
                return _OTRounding;
            }
            set
            {
                if(_OTRounding!=value)
                {
                    _OTRounding = value;
                    RaisePropertyChange("OTRounding");
                }
            }
        }

        decimal _EarlyOTTimeBuffer;
        public decimal EarlyOTTimeBuffer
        {
            get
            {
                return _EarlyOTTimeBuffer;
            }
            set
            {
                if(_EarlyOTTimeBuffer!=value)
                {
                    _EarlyOTTimeBuffer = value;
                    RaisePropertyChange("EarlyOTTimeBuffer");
                }
            }
        }

        string _EarlyOTRounding;
        public string EarlyOTRounding
        {
            get
            {
                return _EarlyOTRounding;
            }
            set
            {
                if(_EarlyOTRounding!=value)
                {
                    _EarlyOTRounding = value;
                    RaisePropertyChange("EarlyOTRounding");
                }
            }
        }  

        public event PropertyChangedEventHandler PropertyChanged;
        void RaisePropertyChange(string prop)
        {
            if(PropertyChanged !=null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }

View Model

class EmployeeTypeViewModel:ViewModelBase
    {
        private ObservableCollection<EmployeeType> _EmployeeTypeList = new ObservableCollection<EmployeeType>();       
        private ObservableCollection<TimeFormat> _ThreeTimeFormat = new ObservableCollection<TimeFormat>();

        public ObservableCollection<TimeFormat> ThreeTimeFormat
        {
            get
            {
                return _ThreeTimeFormat;
            }
            set
            {
                _ThreeTimeFormat = value;
                RaisePropertyChanged("ThreeTimeFormat");
            }
        }
        public ObservableCollection<EmployeeType> EmployeeTypeList
        {
            get
            {
                return _EmployeeTypeList;
            }
            set
            {
                _EmployeeTypeList = value;
                RaisePropertyChanged("EmployeeTypeList");
            }
        }        

        public EmployeeType _SelectedEarlyOTRounding;
        public EmployeeType SelectedEarlyOTRounding
        {
            get
            {
                return _SelectedEarlyOTRounding;
            }
            set
           {
                if (_SelectedEarlyOTRounding != value)
                {
                    _SelectedEarlyOTRounding = value;
                    RaisePropertyChanged("SelectedEarlyOTRounding");

                }
            }
        }


        public EmployeeTypeViewModel()
        {
            _EmployeeTypeList = DataAccess.EmployeeTypeDataAccessor.GetAllEmployeeTypes();           
            ThreeTimeFormat = TMSHelper.GetThreeTimeFormat();
        }
    }

View

 <UserControl.Resources>
        <ViewModels:EmployeeTypeViewModel x:Key="ViewModel"/>
    </UserControl.Resources>
    <Grid DataContext="{Binding Source={StaticResource ViewModel}}">
        <DataGrid Margin="10,10,9.6,10.2" x:Name="empgrid" ItemsSource="{Binding EmployeeTypeList,Mode=TwoWay}" AutoGenerateColumns="False"  >
            <DataGrid.Columns>
                <DataGridTextColumn Header="EmpType" Binding="{Binding EmpType,Mode=TwoWay}"/>
                <DataGridCheckBoxColumn Header="OTRounding" Binding="{Binding OTRounding}"/>
                <DataGridTextColumn Header="Description" Binding="{Binding EmpTypeDesc}"/>               
                <DataGridTextColumn Header="Early OT Time Buffer" Binding="{Binding EarlyOTTimeBuffer}"/>
                <DataGridTemplateColumn Header="Early OT Time Rounding">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox SelectedValuePath="Value" DisplayMemberPath="Key" ItemsSource="{Binding Path=DataContext.ThreeTimeFormat,ElementName=empgrid}" SelectedValue="{Binding EarlyOTRounding,Mode=TwoWay}" SelectedItem="{Binding SelectedEarlyOTRounding}"  />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>
            </DataGrid.Columns>

        </DataGrid>
    </Grid>

I just realized things is if I changed value in datagrid cell,It's will auto update the EmployeeTypeList in viewmodel.Because i added mode=twoway in itemsource of grid.right? But when i debug, Set of EmployeeTypeList never happen.Why? if my doing process is wrong,please let me known how to do that? If you don't understand,please let me known.Thanks.

2条回答
霸刀☆藐视天下
2楼-- · 2019-09-20 09:30

You probably just don't understand to binding completly at this point and it is okay.

Mode=TwoWay means that binded property will be changed on the UI when value is changed in the underlying object and also when user change the value on the UI.

In your case you should have to replace collection on the UI to notice the change. So, far you are changing content of the ObservableCollection and because of that you are not getting any notification on collection level. You should have get notification for EmpType when you change it on the UI.

Is it clear?

查看更多
别忘想泡老子
3楼-- · 2019-09-20 09:55

One of the BindingMode values. The default is Default, which returns the default binding mode value of the target dependency property. However, the default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings.

(source: MSDN )

so generally where it is possible to edit usually does not need to inform

now, for your combobox to work correctly try this.

I usually use it and works perfectly

<DataGridComboBoxColumn Header="Early OT Time Rounding" 
                        DisplayMemberPath="Key"  
                        SelectedValuePath="Value" 
                        SelectedValueBinding="{Binding EarlyOTRounding, UpdateSourceTrigger=PropertyChanged}"   
                        >
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.ThreeTimeFormat, UpdateSourceTrigger=PropertyChanged}"/>
            <Setter Property="Width" Value="280" />
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.ThreeTimeFormat, UpdateSourceTrigger=PropertyChanged}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

attention to this DataGridComboBoxColumn must have a SelectedValueBinding property set to being an item in your EmployeeTypeList so that the selected value is changed in the list

in your case:

SelectedValueBinding="{Binding EarlyOTRounding, UpdateSourceTrigger=PropertyChanged}"

查看更多
登录 后发表回答