Я помню, что мне нужно было сделать это некоторое время назад. Мне потребовалось около недели исследований и попыток, прежде чем я нашел хорошее решение. Я разместил его здесь:
WPF: Отменить выбор пользователя в привязке к данным ListBox?
FYI, это решение на основе MV-VM (если вы aren используя шаблон MV-VM, вы должны быть!) [/ g3]
Я не верю, что диспетчер может отправить сообщение (или задержать) обновление свойств - это хорошее решение, это скорее обходной путь, который на самом деле не нужен. Следующее решение i полностью mvvm и не требует диспетчера.
В коде представления за крючком к событию SelectionChanged и обновлению источника (то есть виртуальной машины) или цели (то есть V) в соответствии с тем, возвращал ли метод VM.ConfirmChange (...) следующее значение:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(e.AddedItems.Count != 0)
{
var selectedItem = e.AddedItems[0];
if (e.AddedItems[0] != _ViewModel.SelectedFormatType)
{
var comboBoxSelectedItemBinder = _TypesComboBox.GetBindingExpression(Selector.SelectedItemProperty); //_TypesComboBox is the name of the ComboBox control
if (_ViewModel.ConfirmChange(selectedItem))
{
// Update the VM.SelectedItem property if the user confirms the change.
comboBoxSelectedItemBinder.UpdateSource();
}
else
{
//otherwise update the view in accordance to the VM.SelectedItem property
comboBoxSelectedItemBinder.UpdateTarget();
}
}
}
}
Возможно, создайте класс, полученный из ComboBox
, и переопределите OnSelectedItemChanged
(Или OnSelectionChangeCommitted
.)
Я нашел эту хорошую реализацию.
private bool handleSelection=true;
private void ComboBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
if (handleSelection)
{
MessageBoxResult result = MessageBox.Show
("Continue change?", MessageBoxButton.YesNo);
if (result == MessageBoxResult.No)
{
ComboBox combo = (ComboBox)sender;
handleSelection = false;
combo.SelectedItem = e.RemovedItems[0];
return;
}
}
handleSelection = true;
}
источник: http://www.amazedsaint.com/2008/06/wpf-combo-box-cancelling-selection.html
Проверка в обработчике события SelectionChanged
позволяет отменить вашу логику, если выбор недействителен, но я не знаю, как легко отменить выбор события или элемента.
Мое решение заключался в подклассе combo-box WPF и добавлении внутреннего обработчика для события SelectionChanged
. Всякий раз, когда срабатывает событие, мой частный внутренний обработчик вместо этого запускает собственное SelectionChanging
событие.
Если свойство Cancel
установлено на соответствующем SelectionChangingEventArgs
, событие не поднимается, а SelectedIndex
возвращается к своему предыдущему значению. В противном случае создается новый SelectionChanged
, который затеняет базовое событие. Надеюсь, это поможет!
EventArgs и делегат обработчика для события SelectionChanging:
public class SelectionChangingEventArgs : RoutedEventArgs
{
public bool Cancel { get; set; }
}
public delegate void
SelectionChangingEventHandler(Object sender, SelectionChangingEventArgs e);
Внедрение класса ChangeComboBox:
public class ChangingComboBox : ComboBox
{
private int _index;
private int _lastIndex;
private bool _suppress;
public event SelectionChangingEventHandler SelectionChanging;
public new event SelectionChangedEventHandler SelectionChanged;
public ChangingComboBox()
{
_index = -1;
_lastIndex = 0;
_suppress = false;
base.SelectionChanged += InternalSelectionChanged;
}
private void InternalSelectionChanged(Object s, SelectionChangedEventArgs e)
{
var args = new SelectionChangingEventArgs();
OnSelectionChanging(args);
if(args.Cancel)
{
return;
}
OnSelectionChanged(e);
}
public new void OnSelectionChanged(SelectionChangedEventArgs e)
{
if (_suppress) return;
// The selection has changed, so _index must be updated
_index = SelectedIndex;
if (SelectionChanged != null)
{
SelectionChanged(this, e);
}
}
public void OnSelectionChanging(SelectionChangingEventArgs e)
{
if (_suppress) return;
// Recall the last SelectedIndex before raising SelectionChanging
_lastIndex = (_index >= 0) ? _index : SelectedIndex;
if(SelectionChanging == null) return;
// Invoke user event handler and revert to last
// selected index if user cancels the change
SelectionChanging(this, e);
if (e.Cancel)
{
_suppress = true;
SelectedIndex = _lastIndex;
_suppress = false;
}
}
}
В WPF динамически устанавливается объект с помощью
if (sender.IsMouseCaptured)
{
//perform operation
}