[WPF] Интересный баг про Binding и VM
От: BluntBlind  
Дата: 17.01.11 07:51
Оценка:
Интересный баг/особенность про 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 не соответствующими тому, что ввел и видел пользователь.
wpf bug binding vm viewmodel button isdefault
Re: [WPF] Интересный баг про Binding и VM
От: MxMsk Португалия  
Дата: 17.01.11 08:25
Оценка: 3 (1)
Здравствуйте, BluntBlind, Вы писали:

BB>Интересный баг/особенность про update биндига и данных во ViewModel на stackoverflow:

BB>How not to lose binding source updates?
Эти грабли стары как мир! Помнится, когда я еще делал свои первые шаги в Delphi, тоже часто напарывался на такое. Делал обработчик на потерю фокуса, где обновлял что-то, а про Default кнопку забывал.

BB>Что думаете, какие решения есть?

1) Делать копию объекта для редактирования в режиме PropertyChanged. Менять объект при принятии изменений пользователем.
2) При нажатии кнопки, вызывать UpdateSource всех биндингов с LostFocus.
Re[2]: [WPF] Интересный баг про Binding и VM
От: BluntBlind  
Дата: 18.01.11 10:39
Оценка: 6 (1)
Здравствуйте, 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;
        }
    }
}
wpf bug binding vm viewmodel button isdefault
Re[3]: [WPF] Интересный баг про Binding и VM
От: MxMsk Португалия  
Дата: 18.01.11 11:19
Оценка: 8 (1)
Здравствуйте, BluntBlind, Вы писали:

BB>Я предложил другой вариант он там идет под заголовком "What you think about proxy command and KeyBinding to ENTER key?", но ТС предпочел другое решение и +300 к карме ушло не мне

BB>Хотя я в будущем в такой ситуации предпочту свое решение, оно мне кажется лучше ... но там видно будет
С одной стороны в предложенном решении модель, пусть и представления, начинает решать проблемы конкретной реализации view. И всё же, оно мне кажется лучше команды. Когда начинаешь затачивать критичные хаки на клаву и прочие устройства ввода — это очень ненадежно. Я вообще стараюсь так не делать, потому что не всегда удается учесть все нюансы. Вариант, когда модель подготовлена к отложенности внесения изменений, работает сто процентов.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.