how to use style defined in xaml resource dictionary? - wpf

I have a a IMultiValueConverter that dynamically creates TextBlock controls. The issue is that it has no styles.
How can I tell my new TextBlock to use a style that was defined in my XAML resource dictionary?

See the following question: how to use DynamicResource in the code behind?
Use SetResourceReference, it's equivalent to use DynamicResource in Xaml
So if your Style has the Key myTextBlockStyle
TextBlock textBlock = new TextBlock();
textBlock.SetResourceReference(FrameworkElement.StyleProperty, "myTextBlockStyle");

I have never tried this before, and depending on what your converter is doing, I think if your XAML resource dictionary is external, then link it into the Window where you are displaying the TextBlocks:
<Window.Resources>
<ResourceDictionary Source="[the path to the resource dictionary]"/>
</Window.Resources>
Then in your textblocks, ensure they have the Style attached that is defined in the resource dictionary. If the textblocks are being created in code behind I believe you should be able to use FindResource to locate the style that is linked in by the resource dictionary. Then do something like this:
textBlock1.Style = (Style)FindResource("myTextBlockStyle");

Related

Define Style in ResourceDictionary, but EventSetter locally

I have restyled a DataGrid and it got rather complex so I moved the styles (DataGrid, DataGridCell, DataGridRow,...) to a ResourceDictionary. I gave all of them a x:Key and referenced them e.g. as DataGrid.RowStyle="{StaticResource SuperRowStyle}". Now I want to use an EventSetter on the Row as well, but obviously I can't set it in the ResourceDictionary, but I can't set it in the Window as well, since it gets overridden by the RowStyle property. How can I do this?
BR,
Daniel
I'll answer it myself as a good solution is provided in the comments. I create a style in the window where I need the EventSetter and use BasedOn with the needed style.
Now I want to use an EventSetter on the Row as well, but obviously I can't set it in the ResourceDictionary ..
Yes, you can provided that you add a code-behind file to the ResourceDictionary:
Is it possible to set code behind a resource dictionary in WPF for event handling?
The handler must be defined in the same class as the EventSetter.

How can data templates in generic.xaml get applied automatically (redux)?

This is a follow-up to a question posted by Thiado de Arruda. In short, he wanted to have a DataTemplate in his generic.xaml file, but the template wasn't being applied.
The answer given suggested placing the DataTemplate in the ControlTemplate.Resources for the control that hosted his custom type. This works very well, however, suppose that he needed the DataTemplate to apply in other places, not just within the host control. Would it be necessary to copy the DataTemplate to the ControlTemplates of every other host control?
Edit (restating question):
I am developing a WPF application using MVVM design principles. MainWindow.xaml contains the structure of the UI, and all of the styling is coded in Themes\generic.xaml. (The behavior is coded in a separate view model class, but that's irrelevant.) As part of the UI, I created a subclass of ListBox (MyListBoxSubClass) to display a collection of an ordinary .Net object of my own creation (MyObject). MyListBoxSubClass has a style in generic.xaml that redefines the Template property, and it gets applied as expected. I also have a DataTemplate for MyObject in generic.xaml, but this does not get applied. According to the above link, I have to place the DataTemplate in the Resources collection of the ControlTemplate for MyListBoxSubClass in order for this DataTemplate to be applied. This works wonderfully.
My question is how to get the DataTemplate to apply to MyObject everywhere in my application without having to duplicate the DataTemplate? I've tried adding a key to the DataTemplate and referencing it where I need it, but for some reason, I get a XAML parse error at runtime, and Resharper says that it can't resolve my DataTemplate key.
Add the data template in a separate resource dictionary in another XAML file.
Bring the XAML file into your generic.xaml control template resources:
<ControlTemplate ...>
<ControlTemplate.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="wherever.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ControlTemplate.Resources>
</ControlTemplate>
Then wherever else you want to use this data template, you can bring it into merged dictionary of resources of wherever you want - user control, window, another control template, etc...
<Window x:Name="someWindow">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="wherever.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
</Window>
Hope this helps.

Apply static resource style to UIElement created in converter

I am binding the ItemsSource of an ItemsControl to a Textbox and then using a converter to create UIElement objects based on the Text property of the Textbox. I also have a static resource style that I want to apply to the elements I create.
The problem I'm having is how to set the style of the items created in the converter to the static resource since I don't have access to the static resources in my converter class.
To use StaticResource in the Converter you could send the Style as ConverterParameter.
If you're already using the ConverterParameter you could make the Converter derive from DependencyObject, add a Dependency Property and set it to the Style on the creation of the Converter.
But the easiest solution is probably to use DynamicResource instead if you know the key of the resource.
The following Xaml
<UIElement Style="{DynamicResource styleKey}" />
is equivalent to the following C# code
myUIElement.SetResourceReference(StyleProperty, "styleKey");
Mission impossible! :) you can use ConverterParameter as your static resource, I think. and all will be ok!

How do I reference my FlowDocument

I've defined a FlowDocument in a WPF control library (Add New Item..., FlowDocument -- is the root element of the file). I intend this to be used in several contexts such as in a user control or on a window, referenced in code for data-binding and export to xps, etc. But I can't figure out how to get a reference to an instance of this document. It doesn't seem to create an object in the compiled assembly.
More specifically, this is my problem
<MyUserControl ........ >
<FlowDocumentScrollViewer>
<!-- doesn't work --><namespaceRef:MyFlowDocument />
<FlowDocumentScrollViewer>
</MyUserControl>
The easiest solution is probably to put your FlowDocument inside a Resource Dictionary and then use the x:Key like this
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FlowDocument x:Key="myFlowDocument" ..>
</FlowDocument>
</ResourceDictionary>
<FlowDocumentScrollViewer Name="flowDocumentScrollViewer">
<StaticResource ResourceKey="myFlowDocument"/>
</FlowDocumentScrollViewer>
Otherwise you'll have to set the FlowDocument to build action Embedded Resource and lode it in code behind with something like this
Stream flowDocumentStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DocumentNameSpace.FlowDocumentName.xaml");
FlowDocument flowDocument = (FlowDocument)XamlReader.Load(flowDocumentStream);
flowDocumentScrollViewer.Document = flowDocument;
Update
I think it might be possible to use an ObjectDataProvider to load the FlowDocument if you want to look into it. Anyway, a ResourceDictionary seems like the easy way out.

Is it possible to set code behind a resource dictionary in WPF for event handling?

Is it possible to set code behind a resource dictionary in WPF. For example in a usercontrol for a button you declare it in XAML. The event handling code for the button click is done in the code file behind the control. If I was to create a data template with a button how can I write the event handler code for it's button click within the resource dictionary.
I think what you're asking is you want a code-behind file for a ResourceDictionary. You can totally do this! In fact, you do it the same way as for a Window:
Say you have a ResourceDictionary called MyResourceDictionary. In your MyResourceDictionary.xaml file, put the x:Class attribute in the root element, like so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyCompany.MyProject.MyResourceDictionary"
x:ClassModifier="public">
Then, create a code behind file called MyResourceDictionary.xaml.cs with the following declaration:
namespace MyCompany.MyProject
{
partial class MyResourceDictionary : ResourceDictionary
{
public MyResourceDictionary()
{
InitializeComponent();
}
... // event handlers ahead..
}
}
And you're done. You can put whatever you wish in the code behind: methods, properties and event handlers.
== Update for Windows 10 apps ==
And just in case you are playing with UWP there is one more thing to be aware of:
<Application x:Class="SampleProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- This will NOT work -->
<!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->
<!-- Create instance of your custom dictionary instead of the above source reference -->
<rd:MyResourceDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
I disagree with "ageektrapped"... using the method of a partial class is not a good practice. What would be the purpose of separating the Dictionary from the page then?
From a code-behind, you can access a x:Name element by using:
Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
...
}
You can do this in the OnApplyTemplate method if you want to hookup to controls when your custom control loads. OnApplyTemplate needs to be overridden to do this. This is a common practice and allows your style to stay disconnected from the control. (The style should not depend on the control, but the control should depend on having a style).
Gishu - whilst this might seem to be a "generally not to be encouraged practice" Here is one reason you might want to do it:
The standard behaviour for text boxes when they get focus is for the caret to be placed at the same position that it was when the control lost focus. If you would prefer throughout your application that when the user tabs to any textbox that the whole content of the textbox was highlighted then adding a simple handler in the resource dictionary would do the trick.
Any other reason where you want the default user interaction behaviour to be different from the out of the box behaviour seems like good candidates for a code behind in a resource dictionary.
Totally agree that anything which is application functionality specific ought not be in a code behind of a resource dictionary.
Adding on....these days, with the advent of {x:Bind ...}, if you want to put your DataTemplate into a shared ResourceDictionary file, you are required to give that file a code behind.
XAML is for constructing object graphs not containing code.
A Data template is used to indicate how a custom user-object is to be rendered on screen... (e.g. if it is a listbox item) behavior is not part of a data template's area of expertise. Redraw the solution...

Resources