Why isn't a property in my ViewModel updated when DataGrid changes?

后端 未结 1 1632
轮回少年
轮回少年 2021-01-27 08:41

I\'m trying to create a UserControl, that will let me edit a Dictionary of type Dictionary in a grid (just editing entries so far, not adding o

相关标签:
1条回答
  • 2021-01-27 09:17

    There's actually two issues here: your DictionaryEntry class should implement INotifyPropertyChanged to work correctly with the binding engine, and secondarily it should implement IEditableObject because you want to edit items in a data grid and avoid 'random results'. So your class should look something like this...

    public class DictionaryEntry : INotifyPropertyChanged, IEditableObject
    {
        private string _k;
        [Description("The key")]
        public string K
        {
            [DebuggerStepThrough]
            get { return _k; }
            [DebuggerStepThrough]
            set
            {
                if (value != _k)
                {
                    _k = value;
                    OnPropertyChanged("K");
                }
            }
        }
        private string _v;
        [Description("The value")]
        public string V
        {
            [DebuggerStepThrough]
            get { return _v; }
            [DebuggerStepThrough]
            set
            {
                if (value != _v)
                {
                    _v = value;
                    OnPropertyChanged("V");
                }
            }
        }
        #region INotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string name)
        {
            var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion
        #region IEditableObject
        public void BeginEdit()
        {
            // implementation goes here
        }
        public void CancelEdit()
        {
            // implementation goes here
        }
        public void EndEdit()
        {
            // implementation goes here
        }
        #endregion
    }
    

    In your ViewModel (or code behind) you would instantiate it like this...

        public ObservableCollection<DictionaryEntry> MyItems { get; set; } 
        public ViewModel()
        {
            MyItems = new ObservableCollection<DictionaryEntry>();
            MyItems.Add(new DictionaryEntry{K="string1", V="value1"});
            MyItems.Add(new DictionaryEntry { K = "color", V = "red" });
        }
    

    ...which is pretty close to what you have. And the Xaml would look like this...

        <DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="True">
        </DataGrid>
    

    Those things will bring about the behaviour you are after. I.e., edits will be sticky.

    On the IEditableObject interface vis-à-vis DataGrids, it's a known 'gotcha' and there's a description of it here... http://blogs.msdn.com/b/vinsibal/archive/2009/04/07/5-random-gotchas-with-the-wpf-datagrid.aspx

    which says...

    If you are not familiar with IEditableObject, see this MSDN article which has a good explanation and code sample. The DataGrid has baked in functionality for transactional editing via the IEditableObject interface. When you begin editing a cell, the DataGrid gets into cell editing mode as well as row editing mode. What this means is that you can cancel/commit cells as well as cancel/commit rows. For example, I edit cell 0 and press tab to the next cell. Cell 0 is committed when pressing tab. I start typing in cell 1 and realize I want to cancel the operation. I press ‘Esc’ which reverts cell 1. I now realize I want to cancel the whole operation so I press ‘Esc’ again and now cell 0 is reverted back to its original value.

    0 讨论(0)
提交回复
热议问题