Accessing external resources with C# - wpf

I have a wpf application where I want to hide some of the code complexity by creating resource dictionaries.
I have an external file called "SubFolder\LoginPanel.xaml".
I created it as a resource dictionary, and added the reference to the App.xaml file.
In LoginPanel.xaml I have some custom colors defined, brushes, and two storyboards, sbShowLoginMenu, sbHideLoginMenu.
In my MainWindow.xaml I can reference the defined brushes without any problems. However, I want to access my storyboards as well, but from C# code behind for mouse enter.
If I copy the story boards to the MainWindow.xaml file the storyboard works correctly, if I remove it from MainWindow.xaml it does not see the resource. It only sees the resources defined in the MainWindow.xaml.
My question is how do I get my code to work so that I can access the storyboard items from the resource dictionary?
My guess is that I have to add something to the 'Window' tag such as xmlns:rd="clr-namespace:LoginPanel". I know this is not the right syntax but I could not find any documentation for this type of problem.
EDIT: When I try var sb = FindResource("sbShowLoginMenu"), the debugger returns 'resource not found.'.

Well, finally I was able to craft a search criteria that gives the right answer.
Storyboards in ResourceDictionary
Basically storyboards are stateful objects and cannot be placed in a resource dictionary.

Related

Set resource URI of .xaml component

I have a .xaml UserControl named MyUserControl.xaml and I want to set its resource URI.
Per default, WPF generates a URI that includes a resource name, which is equal to the resource it belongs to such as
"/MyNamespace;component/myusercontrol.xaml"
for the .xaml named MyUserControl.xaml
How can I have a UserControl MyUserControl.xaml and make WPF generate an individual resource identifies such as
"/MyNamespace;component/myusercontrol_A.xaml" or
"/MyNamespace;component/myusercontrol_B.xaml" ?
The reason why I want to do that is described here.
In the image below you can see the resource identifier I am talking about:
and therein:
Note, that that question is the origin of this question and might help to understand its background.
After a week suffering and laboring with this issue, I finally found both the reason for the problem and its solution.
The problem lies within the auto-generated *.g.i.cs file, which is called by the InitializeComponent() method of a UserControl, as seen by the following:
This file generates a string (a Resource Locator) that expresses the path to that xaml-component, as seen by the following:
Now, if you have multiple versions of the same assembly and both versions include the same xaml-file, WPF does not know what xaml-file to instantiate, because the Resource Locator only references the name of the assembly but not its version.
This results in a TargetInvocationException, saying that
{"The component 'MyNamespace.MyUserControl' does not have a resource identified by the URI '/MyAssembly;comoponent/myusercontrol.xaml'"}
as follows:
The simple (but most definitely not obvious) solution for this is to add the version of the assembly to this Resource Locator. This can be achieved by modifying the build-file of the project by adding the <AssemblyVersion>-tag as follows:
Credits for this go to:
this blog
this SO thread

Silverlight accessing Storyboard from another Class

I'm facing a problem that I probably can't solve on my own, I'm working on a solution now for 2 days and browsed a lot in other Forums etc. - but it seems like that I just don't get it.
My problem
I have a Storyboard called "getVisible" in my UserControl "MainPage" that I want to access in another class called "test.cs"
However, as the Storyboard is defined in the MainPage.xaml and only the App Resources are accessible, do I face the problem that I can't load Storyboards from another class.
Any ideas how to solve that?
~regards Matt
One option to get the storyboard from test.cs is to create an instance of MainPage.
(new MainPage()).Resources["getVisible"];
Alternatively though, you may wish to consider creating the resources in a separate resource dictionary and then referencing that shared resource dictionary from both loactions.

TextBlock foreground being reset to inherited value after dynamic resource from merged dictionary is applied

EDIT: I was able to reproduce this in a very stripped-down version of the application. Here is a link to the .zip file
http://www.mediafire.com/?cn918gi15uph1xe
I have the module add the view to two different regions - the status bar region along the top is where the issue occurs. The weird part is, when the same view type is added to the main region, there are no problems. The status bar region is an ItemsControl and the main region is a ContentPresenter. That is the only difference.
Please let me know if you have any insight! Thanks.
-----Original Post-----
Hello all,
I am seeing some weird behavior with WPF. I'm using .NET 4 and PRISM v4. The way we have our application structured is that the skin resource dictionaries exist in their own assembly. The modules do not reference this assembly - instead we have a skin manager class that reads from a config file which skin we want and loads the appropriate components into a merged dictionary. The merged dictionary is set in the Application resources (we clear out the Application.Resources.MergedDictionaries before we add it). The idea is that we can later switch skins at runtime if needed, and the modules don't need to know about the skins until runtime.
Then in our xaml we are referencing styles using DynamicResource. The problem has to do with a TextBlock style defined in the skin and referenced by key, such as
<TextBlock Style="{DynamicResource someKey}" ... />
The style defines the font family, font size, and foreground. The font family and size are applied correctly (I verified this). The foreground, however, is always black. I used Snoop and WPF Inspector to see that the foreground value is "inherited" instead of coming from the style.
I also have a control that inherits from TextBlock and all it does is add some properties that determine what the text value should be (it doesn't affect the style at all). I was able to add a property changed override for the Foreground property and found out that the style's foreground value gets applied, and then the inherited value gets applied after that. I wasn't able to get the .NET source debugging to work so I couldn't figure out why/where it was being called from the second time...
Here is a link to an old, old post from a guy with the exact same problem - he did not find the answer, but instead a workaround. Unfortunately the workaround only works on the inherited control (I can't set InheritanceBehavior for TextBlocks).
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3501ed19-ab40-4064-81b5-e9b7b9d35b56
My guess is that for TextBlock the foreground property is inherited from its parent unless you explicitly set it on your TextBlock instane. For example if you change the Window or UserControl that this Textblock is in to have a Foreground of blue does it work? One thing you can try doing is in the style instead of setting just Foreground to a color, set TextElement.Foreground. See if that works.
It doesn't explain why the problem exists, but a fix was found here:
http://compositewpf.codeplex.com/discussions/257596
The fix is to load the skins before creating/adding views to the shell.

Set the Style of a control programatically in Silverlight 4?

I am new to Silverlight, but I couldn't find anything about this when I googled it.
I have a button that I am trying to set the style programatically. I have the style defined in a XAML file and I want to pull the style into C# so I can dynamically create a button and assign it this style. So far, this is what I am trying:
button.Style = (Style)Resources["CloseButtonStyle"];
However, it just makes the button have no style. Is there an easy way to do this? I feel like this should be obvious, but I can't get it to work.
You are assuming that your Resources property on the current object is the one that contains the defined style. However, I assume, given the symptoms of your issue, that CloseButtonStyle is actually defined further up the control hierarchy.
Instead, you need to traverse your control hierarchy until you find the resource (or if you know the object that defines it, just refer directly to that object). Unfortunately, Silverlight doesn't include FindResource call like WPF, but it's not too difficult to implement your own.
I can call button1.Style = (Style)Resources["NonExistentKey"]; and it makes my button have no style at all as well, point being that the resource is probably not being found, you won't get an exception.
You directly access the Resources property, but is the style really in the immediate resource dictionary of your Window/UserControl/whatever-you-have?

Wpf: Passing Parameters To A ResourceDictionary

Is there a way to pass parameters to a resource dictionary? I think that I can attach a code behind for the purpose of specifying event handlers, but unfortunately, I also need to access a reference to the parent control from the event handlers. The codebehind, I believe, can be attached by specifying an x:Class attribute for the resource dictionary in xaml, and then creating a class in the same folder, the filename for which is something like [resource dictionary name].xaml.cs.
The purpose is to seperate the code for four hierarchical data templates that I'm using in a single treeview control. The xaml for the treeview is getting a bit long and ugly to look at, so I was hoping to break it down into four resource dictionaries. Any thoughts are welcome!
Andrew
You know you can merge your Resource Dictionaries and then reference the DataTemplate within those dictionaries as needed within the TreeView.
Resource dictionaries sound like a slightly peculiar way to do this. Resource dictionaries are all about sharing instances - they let you use a single instance of something (e.g. a style, a template, a brush, or whatever) from multiple places. They're not really a mechanism for dividing your UI up to simplify individual Xaml files.
The usual mechanism for splitting overly complicated Xaml files up into a few, more manageable smaller files is the user control. (Resource dictionary merging comes into play when you already have a resource dictionary, and it's got too big. But you wouldn't normally introduce a resource dictionary just to start splitting things up. On the contrary, resource dictionaries tend to encourage overly large Xaml files, which is why dictionary merging had to be invented in the first place!)
Most of the time, when I define a data template, I make it contain nothing but a single user control. And if that becomes more complex, I'd split that user control up into more user controls.
From your description, it sounds like your Xaml file has become large because you've got four large hierarchical data templates in there. If you took the body of each template and turned it into a user control, your four templates would now become very simple - something like this:
<HierarchicalDataTemplate x:Key="t1" ItemsSource="{Binding Path=Children}">
<loc:TreeItemTypeOne />
</HierarchicalDataTemplate>
and you'd most likely no longer need to put those templates into separate files. But because the guts of each template is now in a user control, that gives you a place to put your codebehind.
You mention needing a reference to the parent control. That worries me - it makes it sound like you have too much code in your codebehind. But one thing at a time... You could solve that problem by defining a dependency property called ParentControl on your user control, and then put this in the template:
<loc:TreeItemTypeOne
ParentControl="{Binding RelativeSource=
{RelativeSource AncestorType=loc:ParentControlType}}" />
But frankly, as soon as I find myself in a position where I need this, I ask myself: how did I get myself into a position where that seemed necessary, and what can I do to fix that?

Resources