How do you bind resources string to Xaml in Silverlight?
You need to add this reference to the App.xaml
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Then you need to add the string into the <Application.Resources> section
<sys:String x:Key="ResourceString">Resource String</clr:String>
Then all you need to do is refer to *{StaticResource ResourceString}
for example:
<TextBlock Text="{StaticResource ResourceString}"></TextBlock>
Been a while since this was asked and answered, I just wanted to add an additional answer as the first one is not entirely correct. I think he's asking for resources, aka. text written in .resx files. It doesn't make sense at all to add individual strings into the StaticResources collection in the application.
I blogged recently on how to simplify the way you work with resources in Silverlight, enabling both automatic update when the culture changes and a dependency property which gives you simpler syntax.
http://sondreb.com/blog/post/Simplifying-Text-Resources-in-Silverlight.aspx
Related
Please consider the following XAML markup (App.xaml file in Visual Studio 2010):
<Application x:Class="UpdateTrigger.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UpdateTrigger"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
StartupUri="MainWindow.xaml">
<Application.Resources>
<clr:String x:Key="MyString">My string</clr:String>
</Application.Resources>
</Application>
Can I write into MyString much like a variable in a C# program? That is what I am trying to do: I am trying to declare and define a variable through pure XAML, without any code-behind. Is this possible?
CLARIFICATION EDIT:
If I bind MyString, for example, to a TextBox in XAML, can a user type into that TextBox? I tried, but have not been able to do this.
Is it possible to bind to and modify a resource object? Yes and no. You can do it but the object needs to be mutable, so can't be a value type like an Int32 or Boolean, or String which is an immutable reference type. The object also needs to have some property that is being modified (the Path of the Binding) - you can't replace the entire object itself.
The more important question is probably, should you do this. The answer to that is usually no but there can be cases where it can sometimes be useful, for example, declaring a ViewModel instance directly in the View XAML to provide easy designer support. In general it's almost always better to be binding to objects that are part of your code so they can easily interact with other parts of your program without relying on runtime resource lookups. If you have data that's staying in the view, like a TextBlock that just mirrors the value of a TextBox, it's usually better just to bind them directly together with an ElementName Binding rather than adding an extra middleman.
I'm localizing a WPF app using the LocBaml method. Everything works great for UI defined in .xaml files. However I have a few strings that are generated in codebehind that must also be localized. So I tried to take the approach recommended by Microsoft in this article. I have a xaml resource dictionary file as such:
<ResourceDictionary x:Uid="ResourceDictionary_1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- String resource that can be localized -->
<system:String x:Uid="system:String_1" x:Key="localizedMessage">en-US Message</system:String>
</ResourceDictionary>
I then use a third-party tool to generate the localized resources.dll containing a spanish version of the resource dictionary.
However, when I call
string localizedMessage = (string)Application.Current.Resources["localizedMessage"];
localizedMessage always returns the value defined in the en-US version of the dll. I must be misunderstanding something. What do I have to do to get the localized version of the string returned?
After discussion with the OP, the problem is in setting the language too late (in App's OnStartup).
Indeed, the localized resource dictionaries are loaded once, using the current language of the thread. If the thread language changes too late, the resources are already loaded, and no reload is triggered.
A solution in this particular case would be to change the UI thread's locale as early as possible -- that is, in the App's constructor.
Current I have some Views linked to ViewModels using code similar to the following:
<Application.Resources>
<DataTemplate DataType="{ x:Type vm:AgeIndicatorViewModel}">
<v:AgeIndicatorView />
</DataTemplate>
</Application.Resources>
I have two questions regarding this:
Does this method allow me to only link one View to each View Model (I think it does improse this limitation on me, but want to be sure)
When using this method, where should I put all of my DataTemplate declarations? At the moment there are only a few, and they are all in App.Xaml - Is there a better location for these, or is App.Xaml fine / Best location?
The most important question is the second really, as at the moment I want to link my ViewModel to my View in this way, as it requires no external libraries etc.
The way my ViewModels are setup, with their Properties and Commands etc is all working already.
Does this method allow me to only link one View to each View Model (I think it does improse this limitation on me, but want to be sure)
Yes. If you're trying to link multiple ViewModels to multiple Views, you need to encapsulate them within a separate VM, and add a new DataTemplate.
When using this method, where should I put all of my DataTemplate declarations? At the moment there are only a few, and they are all in App.Xaml - Is there a better location for these, or is App.Xaml fine / Best location?
App.Xaml is fine, or really any place in the visual hierarchy above where the DataTemplate will be used.
That being said, if the project gets to be a very large scale project, it's often nicer to start using Merged Resource Dictionaries - this allows you to setup resource dictionaries "near" where you define the View/ViewModel pairs, but then use them at a higher level (ie: merge them into App.Xaml).
Specifying the implicit DataTemplate like you do in your question does tie your View-Model to a single View. You can override this at any control level though, so you could have:
<Window.Resources>
<DataTemplate DataType="{x:Type vm:AgeIndicatorViewModel}">
<v:AgeIndicatorView2 />
</DataTemplate>
</Window.Resources>
This would change the view applied to a view-model for the given window. This can be done on any control at any level.
The benefit of doing this at the app-level though is that it is applied across all windows in your application. While my example above would only be applied to a single window.
In general, the app resources is the best place to define these. Since if you have multiple Windows (i.e. Window1 and Window2), then your view-model will always pick up your implicit DataTemplate.
I have a XAMl string table that is working a treat when i need to refer to it from my controls in XAML.
However I could also do with being able to access it for use in other sections of code - such as validation messages in my model. As you cannot add a resource file to a silverlight I beed to use this.
someone must know what i need to call to get at the resource file, preferably strongly typed so intelli-sense can bail out my forgetfulness.
The Resource File definition
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="test">test</system:String>
</ResourceDictionary>
Instead of listing the strings in XAML, why not using resource files (RESX) directly? This way Visual Studio will create wrappers around your resources using (publicresxfilecodegenerator) and you will be able to get rid of the magic strings, both in code as well as XAML.
You can use the indexer to receive this. Once you have a reference to the resource dictionary, you can use:
string test = (string)resources["test"];
For details, see Referencing Resources from Code.
How can I make a Datatemplate for a ViewModel blendable (designable in expression blend). When I go to resources and try to edit the DataTemplate directly all I see on the Drawingborad is a blank rectangle. This is because the DataTemplate is not bound to anything. Of course I can create a UserControl and create some designtime data in code there to see the template but I now would have to switch back and forth between the resource (to edit) and the usercontrol (to see the result of my edit). Isn't there a more direct way to edit and see my DataTemplate?
It's a bit of a stretch to use, but Blend has a feature called "Design-Time Data" that can help you out. It's tough to get started at first, but once you do a few it's pretty easy. It kind of forces you into a nice pattern for DataContext as well.
Here's a good link on the subject: http://www.robfe.com/2009/08/design-time-data-in-expression-blend-3/
Here's a few choice excerpts:
On Design-Time Sizes
...design time properties can be
safely ignored by other tools and they
are ignored at the runtime
(mc:Ignorable specifies that the
namespace with the "d" prefix can be
ignored).
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Expression Blend uses two design time
properties (d:DesignWidth,
d:DesignHeight) to specify a size for
a control to be used at design time...
On Design-Time Data Sources
I stumbled across d:Datacontext when I
was playing with Blend 3 and tried
adding a “live datasource” to my
window. I thought it was going to
behave just like the old way of
setting a DataContext, but when I ran
my application, there was no data! ...
So the upshot is, now we can write
code like this:
...
<Grid ...
DataContext="{StaticResource GameDataSource}"
d:DataContext="{StaticResource DesignTime_DateDataSource}">
Note that this is for Blend 3 if you want first-party support for these features. They are pretty good - there's even a designer for the design-time data, though I've not looked into those features yet.
Applying To DataTemplates
This is something I sorta made up, but it seems to work. Here I'm using the Design-Time data feature to pull data into the visual element's d:DataContext. You'd have to do this for every top-level element that needed a DataContext set.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!-- Resource dictionary entries should be defined here. -->
<DataTemplate x:Key="MyTemplate">
<TextBlock Text="{Binding Text}" d:DataContext="{StaticResource SampleDataSource}" />
</DataTemplate>
</ResourceDictionary>
The binding syntax is a little bit more explicit if you are using a DataTemplate with a DataType set, but it still works:
<DataTemplate DataType="{x:Type vm:MyViewModel}" >
<TextBlock Text="{Binding Text}"
d:DataContext="{Binding Source={StaticResource SampleDataSource}}" />
</DataTemplate>
This strategy will allow you to see how the DataTemplate will work while editing it directly, however you won't be able to see the result on any view that utilizes that DataTemplate unless you actually run the app. This is a limitation of Blend at the moment due to the fact that they don't appear to be using Mocks, but rather complete replacement objects. If blend ever adds the ability to create a new fake data source by clicking on "New DataSource -> Based on Referenced Object -> MyCustomerObject", then you will be in business.
It's possible you could overcome this limitation with some attached property trickery of your own, but it would be difficult at best.
Alternative
An alternative that will work in every situation, but is a bit more cumbersome to setup is setting up StaticResources that swap out fake data for real data during runtime, but in the designer show static sample data.
Here's a really great article by Karl Shifflett that includes some of these techniques and a few videos on it:
http://karlshifflett.wordpress.com/2008/10/11/viewing-design-time-data-in-visual-studio-2008-cider-designer-in-wpf-and-silverlight-projects/
Hope this helps,
Anderson
This strategy will allow you to see
how the DataTemplate will work while
editing it directly, however you won't
be able to see the result on any view
that utilizes that DataTemplate unless
you actually run the app. This is a
limitation of Blend at the moment due
to the fact that they don't appear to
be using Mocks, but rather complete
replacement objects. If blend ever
adds the ability to create a new fake
data source by clicking on "New
DataSource -> Based on Referenced
Object -> MyCustomerObject", then you
will be in business.
If I want to use acutal ViewModel mocks I guess it is the best way to create actual ViewModel instances and the references them with d:DataContext (e.g. using a ObjectDataProvider or x:Static)