我有一个类KeyCombos
,其中包含Modifier Keys
和Keys
属性:
private ModifierKeys _modifierKeys;
private Key _key;
public ModifierKeys ModifierKeys
{
get { return _modifierKeys; }
set
{
if (_modifierKeys == value)
return;
_modifierKeys = value;
RaisePropertyChanged(nameof(ModifierKeys));
}
}
public Key Key
{
get { return _key; }
set
{
if (_key == value)
return;
_key = value;
RaisePropertyChanged(nameof(Key));
}
}
public KeyCombo(ModifierKeys modifierKeys, Key key)
{
Key = key;
ModifierKeys = modifierKeys;
}
其中RaisePropertyChanged
用于实现INotifyPropertyChanged
。
在我的ViewModel
中,我具有绑定到各种组合键的属性,例如:
private KeyCombo _firstKeyCombo;
public KeyCombo FirstKeyCombo
{
get { return _firstKeyCombo; }
set
{
if (_firstKeyCombo == value)
return;
_firstKeyCombo = value;
// Validation method called here
RaisePropertyChanged(nameof(FirstKeyCombo));
}
}
KeyCombo
的每个部分都在ViewModel
中设置,即:
FirstKeyCombo = new KeyCombo(ModifierKeys.Alt, Key.T);
ViewModel还定义:
public IEnumerable<Key> Keys => _availableKeys;
ObservableCollection<Key> _availableKey; // set to all available keys
public IEnumerable<ModifierKeys> Modifiers => _modifierKeys;
ObservableCollection<ModifierKeys> _modifierKeys; // set to all modifier keys
然后将View
绑定到ComboBoxs
:
<StackPanel Orientation="Horizontal" Grid.Row="13" Grid.Column="2">
<ComboBox ItemsSource="Keys"
SelectedItem="{Binding FirstKeyCombo.Key,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox ItemsSource="Modifiers"
SelectedItem="{Binding FirstKeyCombo.ModifierKey,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
这正常工作,适当的Key
和ModifierKeys
可以正确显示。更改FirstKeyCombo
或Key
时,我需要通过setter更新ModiferKeys
(对ViewModel中KeyCombo
属性的 all 进行验证) )。显然,我尝试使用INotifyPropertyChanged
不能成功做到这一点。我该怎么做才能确保是否通过ModiferKeys
更改了属性(Keys
或Combobox
),FirstKeyCombo
被设置了?
答案 0 :(得分:2)
在ViewModel中,您应“监听”属性的PropertyChanged并设置一个新的KeyCombo。
因此,在创建FirstKeyCombo之后,添加PropertyChangedEventhandler
FirstKeyCombo.PropertyChanged += OnFirstKeyComboPropertyChanged;
应如下所示:
private void OnFirstKeyComboPropertyChanged(object sender, PropertyChangedEventArgs e)
{
//remove the handler
FirstKeyCombo.PropertyChanged -= OnFirstKeyComboPropertyChanged;
//create new object because of referential equlity check in WPF
FirstKeyCombo = new KeyCombo(FirstKeyCombo.ModifierKeys, FirstKeyCombo.Key);
//add the handler to the new object
FirstKeyCombo.PropertyChanged += OnFirstKeyComboPropertyChanged;
}
只需致电
RaisePropertyChanged(nameof(FirstKeyCombo));
事件处理程序中的
是不够的,因为存在对引用相等性的检查,这将导致没有新的对象。
至于评论,这就是使用Reflection的方式。 KeyCombo.Name必须是属性的名称。
private void OnFirstKeyComboPropertyChanged(object sender, PropertyChangedEventArgs e)
{
KeyCombo combo = sender as KeyCombo;
//remove the handler
combo.PropertyChanged -= OnFirstKeyComboPropertyChanged;
//create new object because of referential equlity check in WPF
combo = new KeyCombo(combo.ModifierKeys, combo.Key, combo.Name);
//add the handler to the new object
combo.PropertyChanged += OnFirstKeyComboPropertyChanged;
//Get the ViewModel-Type
Type t = ViewModel.GetType();
//Get the property with the name
PropertyInfo pi = t.GetProperty(combo.Name);
//set the value of the property
pi.SetValue(ViewModel,combo);
}
或带有字典。另外,KeyCombo.Name必须是属性的名称。
private void OnFirstKeyComboPropertyChanged(object sender, PropertyChangedEventArgs e)
{
KeyCombo combo = sender as KeyCombo;
//remove the handler
combo.PropertyChanged -= OnFirstKeyComboPropertyChanged;
//create new object because of referential equlity check in WPF
combo = new KeyCombo(combo.ModifierKeys, combo.Key, combo.Name);
//add the handler to the new object
combo.PropertyChanged += OnFirstKeyComboPropertyChanged;
dictionaryWithAllCombos[combo.Name] = combo;
RaisePropertyChanged(combo.Name);
}
在ViewModel中
public FirstKeyCombo FirstKeyCombo
{
get { return dictionary["FirstKeyCombo"]; }
set
{
dictionaryWithAllCombos["FirstKeyCombo"] = value;
RaisePropertyChanged(nameof(FirstKeyCombo));
}
}