WPF контроли: Как да препращаме към ресурси в анимации?

Написах контрола и успешно създадох сценарий, за да предизвикам анимация по време на задействани събития. Той променя запълването на елипса за определен период от време. Вместо да пиша нов RadialGradientBrush всеки път, когато трябва да променя запълването, предоставих две от тях в ресурсите.

РЕДАКТИРАНЕ: Имам Ellipse, който е основният компонент на контролата и е това, което се влияе от анимацията. Изпълнението му е просто и изглежда така:

<Ellipse Name="myEllipse" Style="{StaticResource DimStyle}" />

Когато го добавя към сценария (вместо да споменавам четката като ресурс), моята анимация работи по предназначение. Когато споменавам четката като ресурс, получавам това изключение:

"Cannot find resource named 'IlluminatedStyle'. Resource names are case sensitive."

Вътре в разкадровката това е мястото, където в момента се споменава:

<UserControl.Resources>
    <Storyboard x:Key="Foo">
        <ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames.KeyFrames>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.01" Value="{StaticResource IlluminatedStyle}" />
                <DiscreteObjectKeyFrame KeyTime="0:0:0.85" Value="{StaticResource DimStyle}" />
            </ObjectAnimationUsingKeyFrames.KeyFrames>
        </ObjectAnimationUsingKeyFrames>
     </Storyboard>
</UserControl.Resources>

Стиловете са много идентични и само свойствата на GradientStop цвета се различават, така че ще дам само един стил за пример.

Реферираният стил

<UserControl.Resources>
    <Style x:Key="IlluminatedStyle" TargetType="Ellipse">
        <Setter Property="Fill">
            <Setter.Value>
                <RadialGradientBrush>
                    <GradientStop Color="#FF215416" Offset="1"/>
                    <GradientStop Color="#FE38DA2E" Offset="0"/>
                    <GradientStop Color="#FE81FF79" Offset="0.688"/>
                </RadialGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

И така, как да направя правилна препратка към стил като този в моя Storyboard?

Забележка: Storyboard и Style се съдържат в един и същ етикет UserControl.Resources, но са разбити за този пример.

РЕДАКТИРАНЕ
Поставих Style преди Storyboard в UserControl.Resources и сега получавам изключение, което гласи:

  "This Freezable cannot be frozen.
   at System.Windows.Freezable.Freeze()
   at System.Windows.Freezable.GetCurrentValueAsFrozen()
   at System.Windows.Media.Animation.TimelineCollection.GetCurrentValueAsFrozenCore(Freezable source)
   at System.Windows.Freezable.CloneCoreCommon(Freezable sourceFreezable, Boolean useCurrentValue, Boolean cloneFrozenValues)
   at System.Windows.Media.Animation.Timeline.GetCurrentValueAsFrozenCore(Freezable sourceFreezable)
   at System.Windows.Freezable.GetCurrentValueAsFrozen()
   at System.Windows.Media.Animation.Clock..ctor(Timeline timeline)
   at System.Windows.Media.Animation.TimelineGroup.AllocateClock()
   at System.Windows.Media.Animation.Clock.AllocateClock(Timeline timeline, Boolean hasControllableRoot)"

person Jeff LaFay    schedule 02.12.2010    source източник
comment
И двете са в един и същи UserControl.Resources, но в какъв ред? Ресурсите, които се препращат (от StaticResource), трябва да са преди този, който го препраща.   -  person Wonko the Sane    schedule 02.12.2010
comment
Стилът е след него в ресурсите. Това има ли значение в WPF? Малко съм изненадан, защото мога да напиша клас след друг в CS файл, но все още препращам към долния клас в най-горния клас и компилирам правилно.   -  person Jeff LaFay    schedule 02.12.2010
comment
Редът има значение при StaticResources, а не при DynamicResources.   -  person Wonko the Sane    schedule 02.12.2010
comment
@Jon, добавих stacktrace, както и стойностите на свойството KeyTime в DiscreteObjectKeyFrames. @Wonko, идеално ли е да направя ресурсите си динамични в този сценарий?   -  person Jeff LaFay    schedule 02.12.2010
comment
Стартирайте приложението вътре в програмата за отстраняване на грешки и когато бъде хвърлено изключение, вижте кой Freezable точно е параметърът на GetCurrentValueAsFrozenCore (3-ти в стека на повикванията). Вие сте този с дебъгера тук, използвайте го. :-)   -  person Jon    schedule 02.12.2010
comment
@jlafay: има компромис в производителността с динамични срещу статични ресурси. Обикновено динамичните ресурси се използват за неща, които ще се променят (т.е. това е един от начините за прилагане на обвързване на етикети за приложения, които позволяват промяна на езика). Тук винаги използвате един и същ ресурс, така че Static вероятно е по-добрият начин. По-добре е да разберете проблема с Freezable, по който @Jon ви е започнал по пътя.   -  person Wonko the Sane    schedule 02.12.2010
comment
Когато изключението хвърля, $exception.Source е WindowsBase, но съм сигурен, че това не ви помага. Опитах точка на прекъсване, при която извикващият метод извиква Begin() в Storyboard с надеждата, че мога да вляза в повикването, но тя се хвърля, когато се извика Begin().   -  person Jeff LaFay    schedule 02.12.2010
comment
Трябва да влезете в дебъгера, тъй като изключението се хвърля, за да инспектирате стека на повикванията. За да направите това, вижте какъв е типът изключение и използвайте тази техника, за да накарате дебъгера да се счупи автоматично: blackwasp .co.uk/VSBreakOnException.aspx   -  person Jon    schedule 02.12.2010
comment
Вече се поврежда в дебъгера, не получавам допълнителна информация. Често задаваните въпроси не са полезни в моя случай, защото все още не знам как да намеря това, което питате. Както казах, той прекъсва, когато се извика методът codebehind на контролата и този метод извиква Begin() в сценария. Къде мога да намеря данните, които питате?   -  person Jeff LaFay    schedule 02.12.2010
comment
Тъй като не стигам докъде, добавих и реда от код, който е основният компонент към контролата. Не мога да преминавам през XAML на анимацията, тъй като не ми позволява да добавям точки на прекъсване. Честно казано, какво търсите?   -  person Jeff LaFay    schedule 02.12.2010


Отговори (2)


Има три причини, поради които Freezable не може да бъде замразен:

  • Има анимирани или свързани с данни свойства.
  • Той има свойства, които се задават от динамичен ресурс.
  • Той съдържа Freezable подобекти, които не могат да бъдат замразени.

Така че първо разберете кой Freezable причинява проблеми и след това проверете горното.

person Jon    schedule 02.12.2010
comment
Благодаря за информацията, нов съм в WPF и оценявам насоките. - person Jeff LaFay; 02.12.2010
comment
Като се има предвид, че това е анимация на сценарий, която хвърля това изключение, предполагам, че има смисъл, но няма смисъл, като се има предвид, че ще се изпълнява, когато не споменавам стойностите на KeyFrame като стилове. Може би трябва да се откажа от повторното използване на кода и да оставя това. Не знам къде да реша проблема. - person Jeff LaFay; 02.12.2010
comment
Намерих решение, но не можах да отстраня грешките в начина, по който искахте. Благодаря все пак. - person Jeff LaFay; 02.12.2010

Виждайки, че съм нов в WPF и XAML, направих грешката да превърна ресурсите си в стил и не осъзнах, че можех просто да направя четките като ресурс и да избегна напълно стиловете.

Запазих препратката към стойностите на DiscreteObjectKeyFrames като статична за новите ресурси на четката. Промених елипсата на това:

<Ellipse Name="myEllipse" Fill="{StaticResource DimBrush" />

Свойството style беше премахнато и аз присвоих четката директно на свойството fill. В тага ObjectAnimationUsingKeyFrames добавих Fill като Storyboard.TargetProperty, тъй като вече не използвах стил за обличане на запълването. DiscreteObjectKeyFrames сега изглеждат така:

<DiscreteObjectKeyFrame KeyTime="0:0:0.01" Value="{StaticResource IlluminatedBrush}" />
<DiscreteObjectKeyFrame KeyTime="0:0:0.85" Value="{StaticResource DimBrush}" />

Моите ресурси са много по-прости, без да са обвити в стил и IMO, по-елегантни. Също така четките са дефинирани преди анимацията в окончателното ми решение.

<UserControl.Resources>
    <RadialGradientBrush x:Key="DimBrush" >
        <GradientStop Color="#FF21471A" Offset="1"/>
        <GradientStop Color="#FF33802F" Offset="0"/>
        <GradientStop Color="#FF35932F" Offset="0.688"/>
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="IlluminatedBrush">
        <GradientStop Color="#FF215416" Offset="1"/>
        <GradientStop Color="#FE38DA2E" Offset="0"/>
        <GradientStop Color="#FE81FF79" Offset="0.688"/>
    </RadialGradientBrush>
    <!-- Storyboard code follows... -->
</UserControl.Resources>

Вече всичко работи по предназначение. Най-доброто предположение, което мога да направя, е, че стиловете не могат да бъдат замразени, тъй като те бяха компонентите, които премахнах, и вече не получавам изключения по отношение на замразяване, което не може да бъде замразено.

person Jeff LaFay    schedule 02.12.2010