Модераторы: gambit, Kefir, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нюанс с Trigger'ами 
V
    Опции темы
Idsa
Дата 18.6.2008, 03:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 2
Всего: 62



В книге, по которой я изучаю WPF, есть следующий пример:
Код

<Window.Resources>
        <Style x:Key="BigFontButtonStyle">
            <Style.Triggers>
                <Trigger Property="Control.IsFocused" Value="True">
                    <Setter Property="Control.Foreground" Value="DarkRed"></Setter>
                </Trigger>
                <Trigger Property="Control.IsMouseOver" Value="True">
                    <Setter Property="Control.Foreground" Value="LightYellow"></Setter>
                    <Setter Property="Control.FontWeight" Value="Bold"></Setter>
                </Trigger>
                <Trigger Property="Button.IsPressed" Value="True">
                    <Setter Property="Control.Foreground" Value="Red"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <Button Style="{StaticResource BigFontButtonStyle}">Hello, Vingrad!</Button>

Далее следует следующий комментарий:
Цитата

Obviously, it's possible to hover over a button that currently has the focus. This doesn't pose a problem because these triggers modify diffrernt properties. But if you click the button, there are two different triggers attempting to set the foreground. Now the trigger for the Button.IsPressed property wins because it's last in the list. It doesn't matter which trigger occurs first - for example, WPF doesn't care that a button gets focus before you click it. The order in which the triggers are listed in your markup is all that matters.

Дословный перевод:
Цитата

Очевидно, что ничто не мешает навести мышь на кнопку, у которой уже есть фокус. Это не вызовет проблему, потому что эти триггеры (прим. имеются в виду тригеры Control.IsFocused и Control.IsMouseOver) изменяют разные свойства. Однако если вы кликните по кнопке, будут задействованы два тригера, пытающихся изменить свойство Foreground. В этом случае "победит" триггер Button.IsPressed, потому что он последний в списке. Не имеет значения, какой тригер исполнится первым - например, WPF не заботит тот факт. что кнопка получает фокус перед щелчком. Единственное, что имеет значение - порядок, в котором тригеры объявлены в разметке.


Я никак не могу понять этот абзац.
Насколько я понимаю, простой тригер срабатывает, если искомое свойство принимает заданное значение. Тогда в приведенном примере с щелчком по кнопке сначала должен сработать тригер Control.IsFocused. Затем свойство IsPressed станет true. Тогда сработает тригер Button.IsPressed.
Это то, как я представляю себе выполнение тригеров. Однако, судя по описанию, тригеры срабатывают целиком после изменения двух свойств: IsFocused и IsPressed. Но я в упор не пойму, как так может быть, если простые тригеры завязаны на DependencyProperties.


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
Kefir
Дата 18.6.2008, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



Так. Не вкурил окончательно. но попытаюсь ответить. Когда мы щёлкаем по кнопке, то одновременно срабатывают и IsPressed и IsFocused. Однако в разметке IsPressed описано больше всего, поэтому именно она и выигрывает.
PM MAIL WWW Skype   Вверх
Idsa
Дата 18.6.2008, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 2
Всего: 62



Цитата(Kefir @  18.6.2008,  13:22 Найти цитируемый пост)
одновременно срабатывают и IsPressed и IsFocused

А как они могут сработать одновременно? Ведь сначала изменится одно свойство, а потом - другое (пусть даже и с разницей в одну наносекунду или одну машинную команду).


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
Kefir
Дата 18.6.2008, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



Idsa, нет. Именно одновременно. Пусть на низком уровне эти события и происходят по очереди, однако это не важно. WPF сделан так, чтобы всё работало логично. Соответственно считается, что эти события происходят именно одновременно. И WPF будет считать их одновременными, а значит они будут бороться за то кто установит Foreground.

Это сообщение отредактировал(а) Kefir - 18.6.2008, 12:38
PM MAIL WWW Skype   Вверх
Idsa
Дата 18.6.2008, 13:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 2
Всего: 62



Kefir, хорошо, пока приму это как данность.


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
PashaPash
Дата 18.6.2008, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 2
Всего: 49



Idsa, в той же книжке, на страницу выше:
Код
When this value occurs, the setters you’ve stored in the Trigger.Setters collection are applied.
Это continious время. Т.е. простой тригер работает все время, пока искомое свойство имеет заданное значение, а не срабатывает один раз по его смене.

Это сообщение отредактировал(а) PashaPash - 18.6.2008, 20:28


--------------------
PM MAIL WWW   Вверх
Kefir
Дата 18.6.2008, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



PashaPash, тут вопрос всё таки о моменте установки этих триггеров. то есть переход из неактивного состояние в активное.
PM MAIL WWW Skype   Вверх
PashaPash
Дата 18.6.2008, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 2
Всего: 49



Kefir, триггер становится активным в тот момент, когда начинает выполнятся его условие. Но триггер не устанавливает свойство в заданное значение в прямом смысле этого слова (не меняет Base value). Т.е. активизация первого триггера не вызывает Foreground=DarkRed. Она подменяет возвращаемое GetValue значение свойства Foreground на DarkRed - effective value. А когда триггер перестает быть активным, он перестает подменять значение свойства.
Вот тут процесс описан во всех подробностях: Dependency Property Value Precedence.


--------------------
PM MAIL WWW   Вверх
Kefir
Дата 19.6.2008, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



PashaPash, ну это всё просто прекрасно. только я так и не понял каким обрахом это относится к теме обсуждения, так что давайте закончим оффтопик.
PM MAIL WWW Skype   Вверх
PashaPash
Дата 19.6.2008, 01:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 2
Всего: 49



Kefir, ну как бы таким образом, что это прямо объясняет почему применяется значение из последнего триггера. В отличие от объяснения "разметке IsPressed описано больше всего, поэтому именно она и выигрывает" или "WPF сделан так, чтобы всё работало логично. Соответственно считается, что эти события происходят именно одновременно.". Потому что на самом деле события - PropertyChanged - происходят последовательно, а разметки не сравниваются по количеству содержимого. Почему прямой ответ на вопрос "почему так происходит" вдруг стал офтопиком?


--------------------
PM MAIL WWW   Вверх
Kefir
Дата 19.6.2008, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



PashaPash, ну, насчёт "больше всего" - это я описался. Думаю и так понятно (хотя бы глядя на код - там "больше всего" не написано). Это раз. Два. WPF действительно задуман так, чтобы была какая-то логика. Скажем так - я не вижу объяснения вопроса в твоих словах. Ты говоришь что триггер не устанавливает base value. хорошо. ты говоришь, что они происходят последовательно (тоже ничего удивительного). Однако ты так и не объяснил почему выбирается последний описаный в коде сеттер. Если точно следовать твоим словам - триггеры срабатывают последовательно. Причём фокус идёт раньше нажатия. Получается, что нажатие всегда будет устанавливаться последним. Однако в то же самое время, если ты возмёшь код ТС и переместишь триггер фокуса в конец - будет устанавливаться цвет, описанный именно в фокус триггере.

Я просто никак не могу понять что ты хочешь сказать.
PM MAIL WWW Skype   Вверх
PashaPash
Дата 19.6.2008, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 2
Всего: 49



Kefir, я хочу сказать что триггеры не срабатывают smile Странно звучит, но сеттер триггера не выставляет значение свойства в момент срабатывания, точнее, он вообще не выставляет значение свойства. Т.е. из того, что фокус идет раньше нажатия, не следует что нажатие будет устанавливаться последним. 
Смотри, вот пример:
Код
<Window.Resources>
        <Style x:Key="BigFontButtonStyle">
            <Style.Triggers>
                <Trigger Property="Control.IsMouseOver" Value="True">
                    <Setter Property="Control.Foreground" Value="Green"></Setter>
                </Trigger>
                <Trigger Property="Button.IsPressed" Value="True">
                    <Setter Property="Control.Foreground" Value="Red"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Button Style="{StaticResource BigFontButtonStyle}">Hello, Vingrad!</Button>

1. Ты наводишь мышкой
2. Триггер на Control.IsMouseOver замечает что свойство IsMouseOver изменилось. Он не меняет Control.Foreground. Он просто вызывает OnPropertyChanged(Control.ForegroundProperty).
3. WFP обнаруживает что поменялось свойство, влияющее на результат рендера. Начинает рендерить гуи. Доходит до места, где нужно отрисовать текст кнопки. WFP берет за основу Base Value.
4. WPF пробегает по триггерам в порядке их объявления и у каждого спрашивает: ты активен и меняешь Control.Foreground? Триггер на IsMouseOver оказывается последним в этом списке, Effective Value принимается равным Green. Рисуется зеленый текст.
5. Ты кликаешь. IsPressed = true.
6. Триггер на Button.IsPressed замечает что свойство IsPressed изменилось. Он не меняет Control.Foreground. Он просто вызывает OnPropertyChanged(Control.ForegroundProperty).
7. WFP обнаруживает что поменялось свойство, влияющее на результат рендера. Начинает рендерить гуи. Доходит до места, где нужно отрисовать текст кнопки. WFP берет за основу Base Value.
8. WPF пробегает по триггерам в порядке их объявления и у каждого спрашивает: ты активен и меняешь Control.Foreground? Триггер на IsPressed оказывается последним в этом списке, Effective Value принимается равным Red. Рисуется красный текст.

Теперь меняем объявления триггеров местами. Единственное, на что это повлияет - это пункт 8.
8b. WPF пробегает по триггерам в порядке их объявления и у каждого спрашивает: ты активен и меняешь Control.Foreground? Триггер на IsMouseOver оказывается последним в этом списке, Effective Value принимается равным Green. Рисуется зеленый текст.


Т.е. Effective Value вообще не зависит от порядка и момента срабатывания триггеров. Оно зависит только от порядка, в котором эти триггеры опрашиваются системой DependencyProperties - от порядка их объявления. 

Это сообщение отредактировал(а) PashaPash - 19.6.2008, 13:23


--------------------
PM MAIL WWW   Вверх
Kefir
Дата 19.6.2008, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



Вот. Теперь моя понял что ты имеешь в виду. Насчёт "считается одновременным" - оно и есть одновременно. То есть по сути в итоге эти триггеры "работают" одновременно (точнее, их опрос проходит массово). Я просто пытаюсь рассказать человечным языком  smile 

За труды  smile 
PM MAIL WWW Skype   Вверх
Idsa
Дата 19.6.2008, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 2
Всего: 62



PashaPash, спасибо за объяснения. Теперь все стало на свои места. +1


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




[ Время генерации скрипта: 0.0586 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.