Вопрос

From this page, I read:

If your application uses custom controls and defines resources in a ResourceDictionary (or XAML Resources node), it is recommended that you either define the resources at the Application or Window object level, or define them in the default theme for the custom controls. Defining resources in a custom control's ResourceDictionary imposes a performance impact for every instance of that control.

Ok... now, I have a UserControl that defines the following resources:

<UserControl ...>
    <UserControl.Resources>
        <Namespace:ImagesConverter x:Key="ImagesConverter" ...
        <Storyboard x:Key="AnimationHide" ...
    </UserControl.Resources>

So, because of the fact I'm creating not less than 100 instances of them at runtime, as the MSDN tutorial says, it would be better to move those resources ad MainWindow or App level. Where's the best location to move them to? MainWindow level, App level or resource file? And why?

And then... how can I use them from their new location? Let's say I have this code inside my UserControl:

m_AnimationHide = (Storyboard)Resources["AnimationHide"];

How should I modify it to reflect those changes? And how should I modify the following UserControl XAML snippet instead?

Source="{Binding Source={x:Static Properties:Resources.MyImage}, Converter={StaticResource ImagesConverter}}"
Это было полезно?

Решение

Personally, I prefer to use App.xaml or seperate ResourceDictionary over adding them all to the Window.Resources, this eliminates clutter in your Window xaml.

This also allows you to easily create Themes for you application as you have them all in one place, so you can copy your existing ResourceDictionary change brush colors etc, the you can choose what ResourceDictionary you want to load and and easily change the entire apperance of your application.

As for accessing the Resouces in your Usercontrol there is no difference on the xaml side, you will continue to use {StaticResource resourceKey} as when you call a StaticResource it searches though the Resource hierarchy to find the Resource.

So if you move you resource from UserControl.Resources to Window.Resources or Application.Resources you don't need to change anything in your xaml code that is accessing though {StaticResource resourceKey}.

As for access in code behind you will use FindResource("resourceKey") instead of Resources["resourceKey"] as FindResource will search the hierarchy for the Resource like the StaticResource does in xaml.

Example:

m_AnimationHide = (Storyboard)FindResource("AnimationHide");

If you want to modify any of these Resources in a specific control and they are frozen you can just create a copy for that instance

Example

var animation = FindResource("AnimationHide") as Storyboard;

m_AnimationHide = animation.Clone();
m_AnimationHide.Completed += m_AnimationHide_Completed;

You can also set x:Shared="false" this will return a new instance of the animation each time from the Resources, this will save copy/pasting the same animation througout your application if you have a complex Resource that you need to change values in.

<Storyboard x:Key="AnimationHide" x:Shared="false" />

Then you will be able to modify the resource locally.

Другие советы

I'd like to expand a bit on the reasoning for moving resources out of the control xaml.

Like you read in the MSDN library, the only technical reason behind moving anything to a higher level is to conserver resources (i.e. memory). Each entry in a ResourceDictionary is created as an object (=instance!) at runtime and takes up memory and the initialization takes a few CPU cycles.

Now the catch with something like the StoryBoard: An object that stores data that is relevant to or even connected to a particular instance of the control - like the instance of the executing animation - has to be created for each instance of the control it should drive. Unless you want all your controls to animate identically and in parallel.

To me it doesn't make much sense to use Clone in code as opposed to just put that thing into the xaml in the first place. The xaml approach takes a bit of copy/paste and thus would mean to modify the animation in more than one place (if you even can re-use something like that across controls) but it will remove the code requirement and still do the same: create an instance of the Storyboard for each instance of the control.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top