Снова WPF
для "бывалых" задачка, уверен, примитивная.
имеем UserControl, в нем - TextBox.
нужно "организовать" Binding mode="OneWayToSource", в общем, чтобы при изменении текста в этом текстбоксе объект DataContent этого UserControl (или его Parent`a) был уведомлен (был вызван setter прибайнднутого проперти).
повсюду натыкаюсь на примеры, как апдэйтить текст в обратную сторону, но это - не проблема. а в обратную сторону - как будто только мне впервые такое понадобилось.
ссылку на работающий пример - идеальная подсказка.
спасибо!
повсюду натыкаюсь на примеры, как апдэйтить текст в обратную сторону, но это - не проблема. а в обратную сторону - как будто только мне впервые такое понадобилось.
А в чем сложность поменять в примерах Mode на OneWayToSource?
чтобы при изменении текста в этом текстбоксе
По умолчанию у свойства Text установлен UpdateSourceTrigger в LostFocus. Вероятно, у Binding тебе его надо установить в PropertyChanged, чтобы изменения происходили при наборе текста.
От вью ко вью модели байндинг работает и так, безо всяких дополнительных реализаций. Указываешь вью контекст данных, и как-то внутри она сама вью модель обновляет. А от вью модели ко вью - нужно реализовать INotifyPropertyChanged во вью модели.
я выбрал неудачный пример. думал, так будет проще и понятнее, оказалось только запутал. попробую ближе к тексту обрисовать мою проблему.
есть UserControl (пусть будет MyUC). в нем один из элементов - Canvas.
хочу, чтобы при клике на канву DataContent получал уведомление. но не просто уведомление, а с некими параметрами. пусть даже просто координаты клика, но лучше что-то другое, что этот MyUC из координат уже сам вычислит.
т.е. где-то в MyUC вызывается некий метод void mouseLB_up(object sender, MouseButtonEventArgs e) {.
и что мы там должны делать, чтобы DataContent каким-то образом "забрал" некий объект?
некошерный метод - в этом методе кастнуть this.DataContent в наш класс, и вызвать его какое-нибудь метод. но тогда нафига нам все эти танцы с мввм-ами? нужно, чтобы по той же схеме все срабатывало. знаю, можно через Interaction.Triggers привязать команду. но не знаю, как в нее параметры подвесить.
в общем, метаюсь в растерянности. даже иногда выпить хочется.
но не просто уведомление, а с некими параметрами. пусть даже просто координаты клика
"Пусть даже", хех. Как раз это не "пусть даже", а вполне себе усложнённый случай. Мышь не является частью вью, поэтому придётся городить какой-то сервис (класс), который будет отслеживать положение мыши, и вязать его со вью или вью моделью. Например, через прикрепляемые поведения. Ну или в коуд бехайнд вью присваивать координаты мыши вью модели, которая доступна через свойство DataContext.
Мышь не является частью вью
ух, как интересно. наверное, она лежит где-то в базе данных, или из интернета скачивается.
зы. мои пояснения немного понос напоминают, но по сравнению с вашими - образец четкости.
ух, как интересно. наверное, она лежит где-то в базе данных, или из интернета скачивается.
Понятия не имею, где она "лежит", но она не является частью вью WPF приложения. Поэтому вью модель не может взаимодействовать с ней так же, как со вью. Но можно взаимодействовать с ней и посредством более глобальных сервисов, перечисленных в ответах по ссылке
How do I get the current mouse screen coordinates in WPF? - Stack Overflow
Кстати, иногда не возбраняется использовать ссылки на WinForms библиотеки. Раньше я в WPF использовал диалог открытия окна, например, из Форм.
но она не является частью вью WPF приложения.
вы, конечно, с большим опытом, и мне не поверите, но я вам ничего другого не могу сообщить, кроме как то, что мышь (как и клавиатура, и не только), безусловно, относятся к GUI. то, что эта аббревиатура означает graphical user interface, не означает, что к этому интерфейсу относятся только пикселы на экране.
В MyUC создаешь свое dependency property. Как, описано здесь.
Если, необходимо, делаешь его readonly (Read-only dependency properties).
при клике на канву
При клике обновляешь значение свойства.
В MyUC создаешь свое dependency property. Как, описано здесь
.я их уже с закрытыми глазами создаю. но все работает без проблем, пока они обновляются СНАРУЖИ, через байндинг. а в обратную сторону что-то пока не найду как.
При клике обновляешь значение свойства.
как? например, вот наше проперти:
public object testobject { get { return GetValue(testobjectProperty); } set { SetValue(testobjectProperty, value); } } public static readonly DependencyProperty testobjectProperty = DependencyProperty.Register("testobject", typeof(object), typeof(MyUC), new FrameworkPropertyMetadata( new PropertyChangedCallback(new_testobject))); private static void new_testobject(DependencyObject source, DependencyPropertyChangedEventArgs e) { (source as MyUC).process_testobject(e.NewValue); } ...
а вот наш обработчик мышки. просто вот так сделать, как здесь? побежал пробовать, но вы скажите, это ли имели ввиду, чтоб я зря не бегал.
void mouseLB_up(object sender, MouseButtonEventArgs e) { this.testobject = e; }
Это всё костыли - работа с обработчиками событий, ещё конвертеры некоторые используют. Более верный путь - добавлять поведения (Behaviors):
<Canvas>
<i:Interaction.Behaviors>
<mouseMoveMvvm:MouseBehaviour MouseX="{Binding PanelX, Mode=OneWayToSource}" MouseY="{Binding PanelY, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Canvas>
С ними можно много чего сделать. Например
<ListBox>
<i:Interaction.Behaviors>
<behaviors:ScrollSelectedItemIntoView />
</i:Interaction.Behaviors>
</ListBox>
А так будете на каждую задачу костыли городить с обработчиками в code behind. Поведения же как раз на dependency properties завязаны и тоже могут использовать события контролов, но лучше всё организуют и проще с их помощью добавлять функциональность потом в другие места (повторное использование).
а если вы хотели бы не координаты передавать, а какие-то более релевантные вещи, в контроле на основании этих координат вычисленные? давайте на привычном вам языке. вы предлагаете метод, который способен передать координаты мыши, которые вообще-то к вью-модели, а тем более к модели, никакого отношения не имеют. я рассматривал этот вариант, но скорее предпочел бы вызвать метод вью-модели из вью непосредственно, так как вытаскивать во вьюмодель не принадлежащий ей функционалитет - последний вариант. тогда, например, если вы когда-то из эстетических соображений измените что-то в этой канве, и нужно будет эти значения иначе вычислять, вам придется делать изменения и во вью, и во вью-модели. а бог не для этого дал нам идею разделения ответственности.
<behaviors:ScrollSelectedItemIntoView />
Кстати, эта штука незаменима, когда делаешь какой CRUD и надо открыть объект для редактирования. Свойства типа выбранного элемента из коллекции можно отобразить комбобоксом или листбоксом. Так вот, в листбоксе выбранный кодом (не пользователем через UI) элемент автоматом не показывается в видимой области списка. Так что приходится приделывать ему такое поведение.
а если вы хотели бы не координаты передавать, а какие-то более релевантные вещи, в контроле на основании этих координат вычисленные? давайте на привычном вам языке. вы предлагаете метод, который способен передать координаты мыши, которые вообще-то к вью-модели, а тем более к модели, никакого отношения не имеют. я рассматривал этот вариант, но скорее предпочел бы вызвать метод вью-модели из вью непосредственно, так как вытаскивать во вьюмодель не принадлежащий ей функционалитет - последний вариант. тогда, например, если вы когда-то из эстетических соображений измените что-то в этой канве, и нужно будет эти значения иначе вычислять, вам придется делать изменения и во вью, и во вью-модели. а бог не для этого дал нам идею разделения ответственности.
Вычислять можно в:
вью:
- конвертерах,
- code behind вью (в событиях, например),
- коде контролов (через dependency property например),
вью модель:
- свойствах вью моделей,
- командах вью моделей,
- методах вью моделей (например, через InvokeCommandAction).
Выбирайте, что вам угодно.
все понял. пошел выбирать.
Не всё так просто. Изначально в WPF была поддержка команд лишь для некоторых контролов. Потом добавили вызов любого метода через расширение InvokeCommandAction из Expression Blend SDK, что по сути отменило потребность в командах. Но это расширение поддерживает только старые версии фреймворка (по 4.5 вроде), а для новых оно не работает. Но вроде как люди свои вещи для этого разработали - где-то находил замену.