Здравствуйте, BluntBlind, Вы писали:
BB>Я предложил другой вариант он там идет под заголовком "What you think about proxy command and KeyBinding to ENTER key?", но ТС предпочел другое решение и +300 к карме ушло не мне
BB>Хотя я в будущем в такой ситуации предпочту свое решение, оно мне кажется лучше ... но там видно будет
С одной стороны в предложенном решении модель, пусть и представления, начинает решать проблемы конкретной реализации view. И всё же, оно мне кажется лучше команды. Когда начинаешь затачивать критичные хаки на клаву и прочие устройства ввода — это очень ненадежно. Я вообще стараюсь так не делать, потому что не всегда удается учесть все нюансы. Вариант, когда модель подготовлена к отложенности внесения изменений, работает сто процентов.
Здравствуйте, MxMsk, Вы писали:
MM>Эти грабли стары как мир!
Да, точно. Назвать это граблями, а не багом будет правильнее, т.к. на уровне самой технологии трудно сказать как должно это дело отрабатывать, ведь это специфика конкретного гуя, его вьюх и моделей. Другое дело, что это создает неудобства.
BB>>Что думаете, какие решения есть?
MM>1) Делать копию объекта для редактирования в режиме PropertyChanged. Менять объект при принятии изменений пользователем.
MM>2) При нажатии кнопки, вызывать UpdateSource всех биндингов с LostFocus.
Я предложил другой вариант он там идет под заголовком "What you think about proxy command and KeyBinding to ENTER key?", но ТС предпочел другое решение и +300 к карме ушло не мне
Хотя я в будущем в такой ситуации предпочту свое решение, оно мне кажется лучше ... но там видно будет
PS Собственно что я предложил:
Использовать специальную прокси команду:
<Window.Resources>
<model:ButtonProxyCommand x:Key="proxyCommand"/>
</Window.Resources>
<Window.InputBindings>
<KeyBinding Key="Enter"
Command="{Binding Source={StaticResource proxyCommand}, Path=Instance}"
CommandParameter="{Binding ElementName=_okBtn}"/>
</Window.InputBindings>
<StackPanel>
<TextBox>
<TextBox.Text>
<Binding Path="Text"></Binding>
</TextBox.Text>
</TextBox>
<Button Name="_okBtn" Command="{Binding Command}">Ok</Button>
</StackPanel>
Сама команда:
public class ButtonProxyCommand : ICommand
{
public bool CanExecute(object parameter)
{
var btn = parameter as ButtonBase;
if (btn == null || btn.Command == null)
return false;
return btn.Command.CanExecute(btn.CommandParameter);
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
if (parameter == null)
return;
var btn = parameter as ButtonBase;
if (btn == null || btn.Command == null)
return;
Action a = () => btn.Focus();
var op = Dispatcher.CurrentDispatcher.BeginInvoke(a);
op.Wait();
btn.Command.Execute(btn.CommandParameter);
}
private static ButtonProxyCommand _instance = null;
public static ButtonProxyCommand Instance
{
get
{
if (_instance == null)
_instance = new ButtonProxyCommand();
return _instance;
}
}
}
Здравствуйте, BluntBlind, Вы писали:
BB>Интересный баг/особенность про update биндига и данных во ViewModel на stackoverflow:
BB>How not to lose binding source updates?
Эти грабли стары как мир!
Помнится, когда я еще делал свои первые шаги в Delphi, тоже часто напарывался на такое. Делал обработчик на потерю фокуса, где обновлял что-то, а про Default кнопку забывал.
BB>Что думаете, какие решения есть?
1) Делать копию объекта для редактирования в режиме PropertyChanged. Менять объект при принятии изменений пользователем.
2) При нажатии кнопки, вызывать UpdateSource всех биндингов с LostFocus.
Интересный баг/особенность про update биндига и данных во ViewModel на stackoverflow:
How not to lose binding source updates?
Что думаете, какие решения есть?
PS Кратко о проблеме:
Многие контролы апдейтят биндинг (записывают данные во ViewModel) на FocusLost. Если у вас есть Button с IsDefault=true, т.е. он будет нажиматься по кнопке ENTER, то возможен Epic Fail:
1. Диалог с текстбоксом и этой самой кнопкой Ok
2. Юзер вводит/меняет текст в этом самом тест боксе.
3. Нажимает на ENTER находясь в этом самом текстбоксе.
Результат:
Фокус не перешел, а значит новый текст НЕ ушел во ViewModel. Но кнопка нажалась и вы выполните команду со старыми данными ViewModel не соответствующими тому, что ввел и видел пользователь.