我正在尝试创建一个UserControl,让我可以在网格中编辑Dictionary<string,string>
类型的词典(目前只编辑条目,而不是添加或删除)。
每当我将DataGrid绑定到Dictionary时,它将网格显示为只读,因此我决定创建一个值转换器,将其转换为ObservableCollection<DictionaryEntry>
,其中DictionaryEntry
只是一个类两个属性Key
和Value
。
这适用于在网格中显示字典,但现在当我对网格进行更改时,我的字典没有被更新。我不确定为什么。
我认为这是我设置绑定的方式或我的值转换器的问题。如果有人能说出一些亮点,那就太棒了。
下面是我能做的最小的演示,展示了我正在做的事情。同样问题是,当我更改网格中的值时,MyDictionary
上的MainViewModel
未更新。为什么呢?
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");
}
}
...
}
MainWindow.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; }
}
}
答案 0 :(得分:1)
这里实际上有两个问题:你的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>
这些事情会带来你所追求的行为。即,编辑将是粘性的。
在IEditableObject
界面与DataGrids相比,它是一个众所周知的“陷阱”,并且在这里有对它的描述...... 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键到下一个单元格。单元格0在何时提交 按下标签。我开始在单元格1中输入并意识到我要取消 操作。我按'Esc'恢复单元格1.我现在意识到我 想要取消整个操作,所以我再次按'Esc',现在是单元格 0将恢复为原始值。