Silverlight AutoCompleteBox NotifyPropertyChanged не обновляет экран
Кажется, у некоторых людей возникают проблемы с обновлением текста AutoCompleteBox в Silverlight, и, к сожалению, я вступил в ряды.
У меня есть производный класс под названием 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://stackru.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...
}
Это позволяет пользователям щелкать по кнопке переключения и выбирать из выпадающего списка, чтобы выбрать опцию или ввести новое значение, например стандартный элемент управления в выпадающем списке.
Мое представление имеет элемент управления EditableCombo, связанный с моделью представления, содержащей свойство Gender;
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);
}
}
Моя модель представления использует объект 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 из раскрывающегося списка. Поле обновляется, пол установлен и все выглядит нормально. Нажатие кнопки "Отменить" успешно изменяет поле на его первоначальное значение - все выглядит просто замечательно.
Однако, когда пользователь пытается повторить изменение, значение на экране не обновляется. Базовое значение изменяется, вызывается свойство get для Gender и правильно устанавливается значение Model.Gender. Но тогда ничего. Экран не обновляется. Элемент управления editablecombo TextBoxChangedEvent не срабатывает, поэтому неудивительно, что значение на экране неверно.
В основном элемент управления не уведомляется об изменении.
Есть идеи?
Обновить:
Представление, содержащее EditableCombo, имеет модель представления, содержащую свойство Gender. Свойство связано вот так;
<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" />
Моя реализация undo / redo отлично работает для нередактируемых элементов управления combo и для editablecombo, когда новые значения вводятся через клавиатуру. Проблема возврата повторяется только тогда, когда свойство было изменено с помощью кнопки-переключателя. Я знаю, что базовые значения корректно обновляются, как объяснено ранее (а также, например, когда ValidatesOnDataErrors включен, когда я повторяю и устанавливаю свойство Gender обратно в допустимое значение, красная граница, означающая ошибку, исчезает - НО, текст остается неизменным).
По какой-то причине событие TextBoxChanged никогда не срабатывает в приведенном выше сценарии. Может ли событие быть обработано в другом месте?
1 ответ
Это работает, если вы добавите эту строку:
Model.Gender = value;
к установщику имущества?