自定义类设置器未更新

时间:2018-09-17 15:43:41

标签: c# wpf

我有一个类KeyCombos,其中包含Modifier KeysKeys属性:

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>

这正常工作,适当的KeyModifierKeys可以正确显示。更改FirstKeyComboKey时,我需要通过setter更新ModiferKeys(对ViewModel中KeyCombo属性的 all 进行验证) )。显然,我尝试使用INotifyPropertyChanged不能成功做到这一点。我该怎么做才能确保是否通过ModiferKeys更改了属性(KeysCombobox),FirstKeyCombo被设置了?

1 个答案:

答案 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));
  }
}