none
WPF. Анимация ForegroundProperty с помощью привязки к свойству класса. RRS feed

  • Вопрос

  • Доброго времени  суток.

    Имеется примитивный проект с стилизированым меню и двумя кнопками.

    Кнопки меняют основной цвет стиля.

    Мне необходимо при наведении курсора на SubMenuItem анимацией поменять Textblock'у свойство Foreground.

    Помогите с поиском решения.

    Вот проект.

    Спасибо за внимание.


    • Изменено iam93 18 ноября 2012 г. 16:18
    17 ноября 2012 г. 20:27

Ответы

  • Не вник изначально в суть ваших действий. Да действительно, если вы заменяете значения ресурса по ходу работы программы, то нужен DynamicResource, но это не очень хороший подход, хотя бы по той причине с которой столкнулись вы.

    Для полного понимания различия между DynamicResource и StaticResource почитайте эту статью.

    Теперь конкретно в вашем случае. Как я понимаю идея в возможности настроить внешний вид программы по ходу работы, другими словами - персонализация. И вот сразу вопрос - как вы планируете сохранять изменения внесенные по ходу работы? Все же замена файлов стиля это больше подходит для шкурок а не для персональной настройки.

    Как решается задача - ваш ресурс должен иметь привязку к некой настройке. Настройку можно менять в ходе работы, ее можно сохранить и восстановить при перезапуске. А ссылку на ресурс с привязкой можно делать через StaticResource и цвет все равно будет обновляться.

    В класс приложения App можно поместить свойство, которое будет возвращать класс настроек, а привязку из стиля можно делать так

    {Binding Source={x:Static Application.Current}, Path=ApplicationData.MainColor}

    где ApplicationData это свойство возвращающее  класс с настройками приложения, реализующий INotifyPropertyChanged

    Потом класс настроек можно сериализовать и восстановить, сохраняя тем самым настройки внешнего вида приложения после перезапуска


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа iam93 18 ноября 2012 г. 16:07
    18 ноября 2012 г. 15:28
    Отвечающий

Все ответы

  • В общих чертах так:

                                        <TextBlock x:Name="TexBltColorCh" Text="{TemplateBinding Header}" HorizontalAlignment="Center" VerticalAlignment="Center">
                                            <TextBlock.Foreground>
                                                <SolidColorBrush x:Name="TexBltColorCh_Foreground" Color="Gray"></SolidColorBrush>
                                            </TextBlock.Foreground>>
                                            <TextBlock.Triggers>
                                                <EventTrigger RoutedEvent="MouseEnter" SourceName="TexBltColorCh">
                                                    <BeginStoryboard>
                                                        <Storyboard>
                                                            <ColorAnimation Storyboard.TargetProperty="Color" Storyboard.TargetName="TexBltColorCh_Foreground" Duration="0:0:0.3" To="White"></ColorAnimation>
                                                        </Storyboard>
                                                    </BeginStoryboard>
                                                </EventTrigger>
                                                             <EventTrigger RoutedEvent="MouseLeave" SourceName="TexBltColorCh">
                                                    <BeginStoryboard>
                                                        <Storyboard>
                                                            <ColorAnimation Storyboard.TargetProperty="Color" Storyboard.TargetName="TexBltColorCh_Foreground" Duration="0:0:0.3" To="Gray"></ColorAnimation>
                                                        </Storyboard>
                                                    </BeginStoryboard>
                                                </EventTrigger>
                                            </TextBlock.Triggers>
                                        </TextBlock>


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    18 ноября 2012 г. 6:50
    Отвечающий
  • И вот тут первая проблема.

    ColorAnimation.To="{DynamicResource myColorKey}" - так не получится... StaticResource не подходит... Пересоздать ColorAnimation никак, так как у нас весь Storyboard заморожен.

    Я пытался создавать и добавлять триггер через код но безрезультатно.

    Спасибо за ответ.

    18 ноября 2012 г. 12:50
  • StaticResource не подходит...

    Почему? Задавать ресурс типа Color DynamicResource'ом просто не логично, так как он не притерпит глобального изменения, например не привратится в String.

    Различия StaticResource и DynamicResource в том, что во втором случае ресурс может изменится в корне, например был SolidColorBrush, а стал LinearGradientBrush. В вашем же случае Color всегда остается Color


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    18 ноября 2012 г. 12:55
    Отвечающий
  • Если задать StaticResource то цвет останется прежним. Сейчас еще раз попробую и перезалью проект.



    • Изменено iam93 18 ноября 2012 г. 14:58
    18 ноября 2012 г. 13:23
  • Как я и говорил, цвет прежний. Как я понимаю StaticResource раз забрал значение кисти и больше не следит за изменением.

    Или нужно обновить стиль?..

    Проект


    Обычно влезаю в сложности...

    18 ноября 2012 г. 14:58
  • Не вник изначально в суть ваших действий. Да действительно, если вы заменяете значения ресурса по ходу работы программы, то нужен DynamicResource, но это не очень хороший подход, хотя бы по той причине с которой столкнулись вы.

    Для полного понимания различия между DynamicResource и StaticResource почитайте эту статью.

    Теперь конкретно в вашем случае. Как я понимаю идея в возможности настроить внешний вид программы по ходу работы, другими словами - персонализация. И вот сразу вопрос - как вы планируете сохранять изменения внесенные по ходу работы? Все же замена файлов стиля это больше подходит для шкурок а не для персональной настройки.

    Как решается задача - ваш ресурс должен иметь привязку к некой настройке. Настройку можно менять в ходе работы, ее можно сохранить и восстановить при перезапуске. А ссылку на ресурс с привязкой можно делать через StaticResource и цвет все равно будет обновляться.

    В класс приложения App можно поместить свойство, которое будет возвращать класс настроек, а привязку из стиля можно делать так

    {Binding Source={x:Static Application.Current}, Path=ApplicationData.MainColor}

    где ApplicationData это свойство возвращающее  класс с настройками приложения, реализующий INotifyPropertyChanged

    Потом класс настроек можно сериализовать и восстановить, сохраняя тем самым настройки внешнего вида приложения после перезапуска


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа iam93 18 ноября 2012 г. 16:07
    18 ноября 2012 г. 15:28
    Отвечающий
  • То есть ApplicationData это класс с набором свойств.

    public class ApplicationData : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private Color mainThemeColor;
            public Color MyMainColor
            {
                get { return mainThemeColor; }
                set {
                    mainThemeColor = value;
                }
            }
        }

    так как то? никогда не работал с ним...



    Обычно влезаю в сложности...


    • Изменено iam93 18 ноября 2012 г. 16:03
    18 ноября 2012 г. 16:03
  • Почти. ApplicationData это поле в классе приложения App.xaml.cs которое устанавливает и возвращает класс настроек, например ApplicationProperty, а вот он уже и является тем, что вы показали в сообщении. Такая хитрость нужна, что бы легко обратится в привязке через x:Static

    К слову тема немного ушла от первоначального вопроса. Может вы как то подкорректируете его что бы было понятнее о чем основная речь в обсуждении.



    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    18 ноября 2012 г. 16:08
    Отвечающий
  • Как при данной структуре  
    public partial class App : Application
    	{
            ApplicationProperty ap;
            public ApplicationProperty ApplicationData
            {
                get{return ap;}
                set{ ap = value;}
            }
    	}
        
    
        public class ApplicationProperty : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private Color mainThemeColor = Colors.Blue;
            public Color MyMainColor
            {
                get { return mainThemeColor; }
                set {
                    mainThemeColor = value;
                }
            }
        }
    написать привязку к стилю?(

    Обычно влезаю в сложности...

    18 ноября 2012 г. 16:33
  • Ну во первых мало реализовать INotifyPropertyChanged, нужно еще в set вызвать событие PropertyChanged с указанием имени свойства. Пример смотрите тут.

    А ваши ресурсы с привязкой задавать так:

    <SolidColorBrush x:Key="MainColor" Color="{Binding Source={x:Static Application.Current}, Path=ApplicationData.MyMainColor}"/>
    Теперь у вас есть ресурс к которому можно обращаться отовсюду, хоть в анимации и котрый будет менятся в случае изменения MyMainColor

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    18 ноября 2012 г. 16:48
    Отвечающий
  • Что то совсем ни как... Класс реализовал:

    public partial class App : Application
    	{
            public string mY;
            ApplicationProperty ap = new ApplicationProperty() { MyMainColor = Colors.Aqua };
            public ApplicationProperty ApplicationData
            {
                get{return ap;}
                set{ ap = value;}
            }
    	}
        
        public class ApplicationProperty : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private Color mainThemeColor;
            public Color MyMainColor
            {
                get { return mainThemeColor; }
                set {
                    mainThemeColor = value;
                    OnPropertyChanged("MainColor");
                }
            }
            protected void OnPropertyChanged(string name)
            {
                PropertyChangedEventHandler handler = this.PropertyChanged;
                if (handler != null)
                    handler(thisnew PropertyChangedEventArgs(name));
            }   
        }

    что передавать в OnPropertyChanged. Программа вылетает, во время применения стиля.

    <ColorAnimation 
           Storyboard.TargetProperty="Foreground.Color" 
           Storyboard.TargetName="TexBltColorCh" 
           Duration="0:0:0.3" 
           To="{Binding Source={x:Static Application.Current}, Path=ApplicationData.MyMainColor}"/>

    Пошагово проходя, видно, он забирает свойство и вылетает после выполнения

    get { return mainThemeColor; }

    Не доведу до ума... 


    Обычно влезаю в сложности...







    • Помечено в качестве ответа iam93 18 ноября 2012 г. 19:22
    • Снята пометка об ответе iam93 18 ноября 2012 г. 19:22
    • Изменено iam93 18 ноября 2012 г. 19:23
    18 ноября 2012 г. 18:45
  • что передавать в OnPropertyChanged. Программа вылетает, во время применения стиля.

    В OnPropertyChanged передается имя свойства. У вас оно MyMainColor, а в OnPropertyChanged вы пишите MainColor вот вам и исключение.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа iam93 19 ноября 2012 г. 20:30
    • Снята пометка об ответе iam93 19 ноября 2012 г. 20:30
    19 ноября 2012 г. 5:13
    Отвечающий
  • Спасибо за помощь.) Про подобный вариант реализации я и не думал, опыта мало...

    Обычно влезаю в сложности...

    19 ноября 2012 г. 20:31