Silverlight AutoCompleteBox NotifyPropertyChanged 不更新屏幕

标签 silverlight inotifypropertychanged autocompletebox

似乎有些人在 Silverlight 中更新文本 AutoCompleteBox 时遇到问题,遗憾的是我已经加入了这个行列。

我有一个像这样的名为 EditableCombo 的派生类;

  public class EditableCombo : AutoCompleteBox
  {
    ToggleButton _toggle;
    Path _btnPath;
    TextBox _textBox;
    ...animation and toggle button stuff...

    public override void OnApplyTemplate()
    {
      ...animation and toggle button stuff...

      //required to overcome issue in AutoCompleteBox that prevents the text being updated in some instances
      //http://stackoverflow.com/questions/8488968/silverlight-5-autocompletebox-bug?rq=1
      _textBox = GetTemplateChild("Text") as TextBox;

      if (_textBox == null)
        throw new NullReferenceException();

      if (_textBox != null)
        _textBox.TextChanged += TextBoxChanged;

      base.OnApplyTemplate();      
    }

    void TextBoxChanged(object sender, TextChangedEventArgs e)
    {
      Debug.WriteLine("text box changed fired new value: " + _textBox.Text);
      Text = _textBox.Text;
      OnTextChanged(new RoutedEventArgs());      
    }

    ...animation and toggle button stuff...
  }

这使用户能够单击切换按钮并从下拉列表中进行选择以选择选项或键入新值,例如标准组合框控件。

我的 View 有一个 EditableCombo 控件绑定(bind)到包含 Gender 属性的 View 模型;
public string Gender
{
  get
  {
    Debug.WriteLine("Gender get executed - Model.Gender = " + Model.Gender);
    return Model.Gender;
  }
  set
  {        
    if (Model.Gender == value) return;        
    MonitoredNotificationObject.RaisePropertyChanged(() => Model.Gender, value, this, true);        
  }
}

我的 View 模型使用 MonitoredNotificationObject 来维护撤消/重做历史并通知任何属性更改;
    public void RaisePropertyChanged(Expression<Func<string>> propertyExpression,
                                     string newValue,
                                     object sender,
                                     bool canChain)
    {
      PropertyExpressionHelper propertyExpressionHelper = new PropertyExpressionHelper(propertyExpression)
                                       {
                                         NewValue = newValue
                                       };

#if DEBUG
      VerifyPropertyExists(propertyExpressionHelper.Name, sender);
#endif

      var monitoredAction = new MonitoredProperty<TViewModel, TModel>(this)
                              {
                                ObjectPropertyName = propertyExpressionHelper.MakeObjectPropertyName(),
                                PropertyExpressionHelper = propertyExpressionHelper,
                                Sender = (TViewModel) sender,
                                CanChain = canChain
                              };

      propertyExpressionHelper.SetToNewValue();
      RaisePropertyChanged(propertyExpressionHelper.Name, sender);
      MaintainMonitorState(monitoredAction);
    }

撤消和重做如下实现(撤消显示);
public override bool UndoExecute(MonitoredObject<TViewModel, TModel> undoAction,
                                 Stack<MonitoredObject<TViewModel, TModel>> redoActions,
                                 Stack<MonitoredObject<TViewModel, TModel>> undoActions)
{
  PropertyExpressionHelper.SetToNewValue();
  redoActions.Push(undoAction);

  var action = (MonitoredProperty<TViewModel, TModel>) undoAction;
  HandleAutoInvokedProperties(action);

  if (action.CanChain)
  {
    if (undoActions.Any())
    {          
      if (CanDoChain(undoActions, action))
        return true;
    }
  }

  action.RaiseChange();
  Sender.RaiseCanExecuteChanges();
  return false;
}

属性更改通知是这样引发的;
protected virtual void RaiseChange()
{
  MonitoredNotificationObject.RaisePropertyChanged(PropertyExpressionHelper.Name, Sender);

  if (RaiseChangeAction != null)
    RaiseChangeAction.Invoke();
}

使用上述方法对于普通文本框来说效果很好,并且成功地允许用户根据需要撤消和重做他们的更改。当用户在字段中键入条目时,这也适用于 EditableCombo - 再次,撤消和重做按预期执行。

问题是当用户从下拉列表中选择 EditableCombo 中的新值时。字段更新,性别设置,一切看起来都很好。单击撤消成功地将字段更改回其原始值 - 一切看起来都很花哨。

但是,当用户尝试重做更改时,屏幕上的值不会更新。基础值已更改,Gender 属性上的 get 被调用,并且 Model.Gender 值已正确设置。但后来什么都没有。画面不更新。可编辑组合控件 TextBoxChangedEvent 不会触发,因此屏幕上的值不正确也就不足为奇了。

基本上没有通知控件更改。

有任何想法吗?

更新:

包含 EditableCombo 的 View 有一个包含 Gender 属性的 View 模型。属性是这样绑定(bind)的;
<EditCombo:EditableCombo ItemsSource="{Binding Genders}"
    ItemTemplate="{StaticResource editableComboDataTemplate}"
    Style="{StaticResource EditableComboStyle}"
    Text="{Binding Path=Gender,
                  UpdateSourceTrigger=PropertyChanged,
                  Mode=TwoWay,
                  ValidatesOnDataErrors=True}"
    TextBoxStyle="{StaticResource editableComboDataEntryField}"
    ValueMemberPath="Value" />

当通过键盘输入新值时,我的撤消/重做实现适用于不可编辑组合控件和可编辑组合控件。重做问题仅在通过下拉切换按钮更改属性时才明显。我知道基础值已按照前面的说明正确更新(例如,当 ValidatesOnDataErrors 处于打开状态时,当我重做并将 Gender 属性设置回有效值时,表示错误的红色边框消失 - 但是,文本保持不变)。

无论出于何种原因,TextBoxChanged 事件在上述情况下都不会触发。会不会是事件正在其他地方处理?

最佳答案

如果添加此行是否有效:

Model.Gender = value;

到属性 setter ?

关于Silverlight AutoCompleteBox NotifyPropertyChanged 不更新屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19728985/

相关文章:

silverlight - 在 Silverlight 中将鼠标悬停在 UI 元素上时将指针设置为手

c# - 最奇怪的组合框异常 : GeneratorPosition '-1,1' "passed to Remove does not have Offset equal to 0". 参数名称:位置

c# - 使用反射初始化对象的自动属性——有什么注意事项吗?

silverlight - 如何在 Mvvm Light 中使用 ViewModelLocator

c# - WPF 绑定(bind)到 TextBlock 未更新

c# - 以类型安全的方式处理 PropertyChanged

c# - 跨序列化对象反射以设置 PropertyChanged 事件

wpf - AutoCompleteBox WPF 中的 ValueMemberPath 绑定(bind)仅返回姓氏搜索中的顶部结果?

silverlight - AutoCompleteBox:不使用向上/向下键进行验证

c# - 如何过滤 AutoCompleteBox 中第一个匹配项的项目列表?