为什么不是';我的ViewModel中的某个属性在DataGrid更改时更新
本文关键字:属性 DataGrid 更新 我的 ViewModel 为什么不 | 更新日期: 2023-09-27 18:25:10
我正在尝试创建一个UserControl,它将允许我在网格中编辑Dictionary<string,string>
类型的Dictionary(到目前为止只是编辑条目,而不是添加或删除)。
每当我将DataGrid绑定到Dictionary时,它都会将网格显示为只读,因此我决定创建一个值转换器,将其转换为ObservableCollection<DictionaryEntry>
,其中DictionaryEntry
只是一个具有两个属性Key
和Value
的类。
这适用于在网格中显示字典,但现在当我对网格进行更改时,我的字典不会更新。我不确定为什么。
我认为这要么是我设置绑定的方式有问题,要么是我的值转换器有问题。如果有人能透露一些信息,那就太棒了。
下面是我能做的最小的演示,展示了我在做什么。同样的问题是,当我更改网格中的值时,MainViewModel
上的MyDictionary
不会更新。。曾经为什么?
MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
_myDictionary = new Dictionary<string, string>()
{
{"Key1", "Value1"},
{"Key2", "Value2"},
{"Key3", "Value3"}
};
}
private Dictionary<string, string> _myDictionary;
public Dictionary<string, string> MyDictionary
{
get
{
return _myDictionary;
}
set
{
if (_myDictionary == value)
return;
_myDictionary = value;
OnPropertyChanged("MyDictionary");
}
}
...
}
主窗口.xaml
<Window ...>
<Window.Resources>
<local:MainViewModel x:Key="MainViewModel"></local:MainViewModel>
</Window.Resources>
<StackPanel Name="MainStackPanel" DataContext="{Binding Source={StaticResource MainViewModel}}">
<local:DictionaryGrid />
<Button Content="Print Dictionary" Click="PrintDictionary"></Button>
</StackPanel>
</Window>
DictionaryGrid.xaml
<UserControl ...>
<UserControl.Resources>
<testingGrid:DictionaryToOcConverter x:Key="Converter" />
</UserControl.Resources>
<Grid>
<DataGrid ItemsSource="{Binding MyDictionary,
Converter={StaticResource Converter}}"
/>
</Grid>
</UserControl>
DictionaryToOcConverter.cs
public class DictionaryToOcConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var collection = new ObservableCollection<DictionaryEntry>();
var dictionary = value as Dictionary<string, string>;
if (dictionary != null)
{
foreach (var kvp in dictionary)
collection.Add(new DictionaryEntry { Key = kvp.Key, Value = kvp.Value });
}
return collection;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var dictionary = new Dictionary<string, string>();
var entries = value as ObservableCollection<DictionaryEntry>;
if (entries != null)
{
foreach (var entry in entries)
dictionary.Add(entry.Key, entry.Value);
}
return dictionary;
}
public class DictionaryEntry
{
public string Key { get; set; }
public string Value { get; set; }
}
}
这里实际上有两个问题:DictionaryEntry
类应该实现INotifyPropertyChanged以正确使用绑定引擎;其次,它应该实现IEditableObject,因为您希望编辑数据网格中的项并避免"随机结果"。所以你的课应该是这样的。。。
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
}
在您的ViewModel(或代码隐藏)中,您可以像这样实例化它。。。
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" });
}
这与你所拥有的非常接近。Xaml会是这样的。。。
<DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="True">
</DataGrid>
这些事情会带来你想要的行为。也就是说,编辑会有粘性。
在相对于DataGrids的IEditableObject
接口上,它是一个已知的"gotcha",这里有它的描述。。。http://blogs.msdn.com/b/vinsibal/archive/2009/04/07/5-random-gotchas-with-the-wpf-datagrid.aspx
上面写着。。。
如果您不熟悉IEditableObject,请参阅MSDN的这篇文章有很好的解释和代码示例。DataGrid已烘焙在通过IEditableObject进行事务编辑的功能中界面当您开始编辑单元格时,DataGrid会进入单元格编辑模式以及行编辑模式。这意味着你可以取消/提交单元格以及取消/提交行。例如,我编辑单元格0,然后按tab键进入下一个单元格。当按tab键。我开始在单元格1中输入,意识到我想取消操作。我按"Esc"键,返回单元格1。我现在意识到想取消整个操作,所以我再次按"Esc",现在是单元格0将恢复为其原始值。