WPF define ConverterCulture/Language in resources - wpf

I would like default culture/language to be defined as resource in order to provide consistent displaying of selected labels. It seems, however it is not possible to define neither Language(XMLLanguage) nor ConverterCulture(CultureInfor) resource, it does not seem to be possible to use a string resource neither:
<TextBlock Text="{Binding Source={x:Static sys:DateTime.Now},
Mode=OneWay, StringFormat={StaticResource DateFormat},
ConverterCulture={StaticResource DefaultCulture},
Language={StaticResource DefaultLang}/>
//....
<Grid.Resources>
<sys:String x:Key="DefaultCutureString">en-GB</sys:String>
<win:XmlLanguage xmlns:win="clr-namespace:System.Windows.Markup;assembly=PresentationFramework" x:Key="DefaultLang">en-GB</win:XmlLanguage>
<g:CultureInfo xmlns:g="clr-namespace:System.Globalization;assembly=mscorlib" x:Key="DefaultCuture">
<x:Arguments>
<sys:String>en-GB</sys:String>
</x:Arguments>
</g:CultureInfo>
</Grid.Resources>
How can I define and apply Culture/Language using Resource?

XmlLanguage and CultureInfo have no default parameterless constructors which means you cannot instantiate them in XAML.
But you could create the resources programmatically and then add them to Grid.Resources (just give the Grid and x:Name of "grid" or similar in the XAML markup to be able to identify it in the code):
grid.Resources["DefaultLang"] = XmlLanguage.GetLanguage("en-GB");
grid.Resources["DefaultCuture"] = new System.Globalization.CultureInfo("en-GB");

Related

How can I find a DataTemplate via code?

Knowing a HierarchicalDataTemplate is defined somewhere in the resource tree (i.e. it could be defined at the app level, in a style, in the window's resources or somewhere in the hierarchy of controls on that window), programmatically, how can you determine which HierarchicalDataTemplate will be applied for a particular data type relative to a specific control?
For instance, in the following example, given that we have an object of type Foo, how can we get the HierarchicalDataTemplate for it--which happens to be defined at the window level here--relative to MainTreeView?
<Window ... >
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type Foo}"
ItemsSource="{Binding Children}">
<TextBlock Text={Binding Name}" />
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView x:Name="MainTreeView" />
</Window>
I've tried the following but it returns null:
var hdt = (HierarchicalDataTemplate)MainTreeView.FindResource(typeof(Foo));
Found it. DataTemplate objects don't use DataType for their default key like Style objects do. Instead, they use a DataTemplateKey object which you get as follows...
var dataTemplateKey = new DataTemplateKey(dataItem.GetType());
var hdt = (HierarchicalDataTemplate)MainTreeView.TryFindResource(dataTemplateKey);
That worked! :)

WPF- Binding properties in a DataTemplate

I'm building a window with a set of rows that share the same layout, but their contents should be different, eg:
| (Label Content:)"Name1" | (Textbox Text)"SomeText" |
| (Label Content:)"Name5" | (Textbox Text)"OtherText" |
I've defined a DataTemplate which basically holds a Grid specifying the size of each column, holds all the elements it requires (a few labels, textboxes, etc.) and sets their common properties.
<UserControl.Resources>
<DataTemplate x:Key="AxisRangeEntry" x:Shared="False">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
....
</Grid.ColumnDefinitions>
<Label x:Name="MyLabel" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center">
...
<TextBox x:Name="MyTextbox" Grid.Column="2" Width="110" HorizontalContentAlignment="Right" />
...
</Grid>
</DataTemplate>
</UserControl.Resources>
Then in my window I start adding the data template as ContentControls in a stack panel:
<ContentControl ContentTemplate="{StaticResource AxisRangeEntry}" />
<ContentControl ContentTemplate="{StaticResource AxisRangeEntry}" />
....
I'm struggling to figure out how I can define certain properties of controls inside the DataTemplate to be bindable to, and bind them to a static value/external property when I start defining the ContentControls. Effectively each ContentControl would need to be able to define things like it's MyLabel content and MyTextbox text.
I've previously created CustomControls, which had DependencyProperties on them, which I could then bind to when adding them on another window. With a DataTemplate however I'm not sure how I would define these fields as bindable and bind to them when including a new version of the template.
Any help would be appreciated.
From what it sounds like, you are not using the MVVM pattern.
For your situation, I'd recommend using MVVM -- take a look at this article for a quick intro for something that would fit your case (ItemsControl with an ItemTemplate)
What you would do is create an ObservableObject to represent each row, and then bind the collection of ObservableObjects to an ItemsControl's ItemsSource, with the ItemTemplate set to the DataTemplate you created. In the DataTemplate, you would specify each binding to the property on the ObservableObject's row, and WPF would bind to the correct instance for each row.
http://www.wpf-tutorial.com/list-controls/itemscontrol/
Either way, DataTemplates are primarily used for templating a certain data-type. If you really need to implement the view in this way, a custom UserControl with dependency properties would be the way to go.
You present a dynamic nature of items to be bound, so this answer will attempt to provide guidance within the parameter's set.
...[to] define certain properties of
controls inside the DataTemplate to be bindable to,
Within a template the binding will default to the parents data context. Simply saying {Binding} will default to that item in the data context. If the bound item has a specific property then use {Binding MyPropertyName}. Just verify that the parent, or its ancestors have a valid data context.
Think of data templates in its final location, as if you had hard coded it there. It will behave the same....
and bind them to a static value/external property when I start defining the
ContentControls.
Since this sounds like it is in a custom control, the datacontext will be the ultimate consumer's datacontext and most likely the datacontext will be worthless.
If it is on a custom control, then use named binding and bind it to a property on the control. For example the control's name, in XAML, is given the name "MyControl" (x:Name="MyControl")and in the template binding, one can path directly to it such as
{Binding MyCustomControlDependencyProperty, ElementName=MyControl}
created CustomControls, which had Dependency properties
With the above rules one can still, and should IMHO, use dependency properties of the custom control to pass on the information from the consumer to the the datatemplate which will use it dynamically..

Adding resource in code and using it as StaticResource

For some reason I am unable to bind to ViewModel properties within DataTemplates on some controls. The result of the binding itself is unpredictable, sometimes it work, sometimes it doesn't. For this reason I am thinking of exposing the ViewModel in some other way besides setting it as DataContext.
First thought was to add ViewModel to Resources collection. I am using TabControls for UI, so whenever a view needs to be displayed, it is done through Data templates.
<DataTemplate DataType="{x:Type vm:SomeViewModel}">
<vw:SomeView />
</DataTemplate>
In this situation the view is instantiated automatically, and its DataContext is set to ViewModel set in template. Is there a way I can make this ViewModel available to View's Resources (ex with key=viewModel), so that I can use it like this:
<TextBlock Text="{Binding SomeProperty, Source={StaticResource viewModel}}" />
I have tried adding it in code, in the Loaded event for the View:
this.Loaded += (s, e) =>
{
this.Resources.Add("viewModel", this.DataContext);
};
Above code is executed before the error pops up that says static resource is not found at run-time, so the resource was added to collection.
Any ideas what can I do?
You can define ViewModel as a resource in XAML like that:
<vm:SomeViewModel x:Key="ViewModel"/>
If you want to Bind to DataContext in a DataTemplate you can use the following:
{Binding Path=DataContext, ElementName=uc}
assuming that your window/usercontrol name is x:Name="uc" , or as #stukselbax wrote:
{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=[UserControl|Window]}}

WPF DataTemplate access to Resources within same ResourceDictionary

Simplified, I have a ResourceDictionary which contains a DataTemplate and a ViewModel-Class.
<ResourceDictionary>
<DataTemplate DataType="Whatever">
<ListBox ItemsSource="{Binding Source={StaticResource MyViewModel}, Path=SomeGlobalData}" />
</DataTemplate>
<MyViewModelClass x:Key="MyViewModel" />
</ResourceDictionary>
Of course the Binding won't work (it'll fire exceptions) because the DataType won't have the resource 'MyViewModel'. But in the VisualTree the "thing" that gets DataTemplated is a child of an object which has the ResourceDictionary merged to its Resources, so there might be a way to access it within runtime.
So my question is: Is there any clean way to access 'MyViewModel' within the DataTemplate?
Your problem is the order these resources are instantiated and the fact that you use StaticResource vs DynamicResource.
A StaticResource provides a value for any XAML property attribute by looking up a reference to an already defined resource. Try to find out more on the subject.
So please move your view model above the data template if you still plan on using StaticResource.

WPF Dynamic resource reference

HI
Am load a string xaml with DynamicResource assigned to a Background property. Is there a way to get the reference of the dynamic resource.
Background="{DynamicResource Color1}"
I want to get the resource reference assigned to a Dependency property at runtime
Pl help
Use FrameworkElement.FindResource Method
this.FindResource("Color1");
Where is the DependencyProperty defined? On the same Window/UserControl? If you simply want to bind to the value of a DependencyProperty you probably want to use regular {Binding ...} syntax instead.
Example 1: If you are binding to a dependency property on a particular control named myControl you can declare it like below.
Background="{Binding ElementName=myControl, Path=Color1}"
Example 2: If you don't want to rely on naming controls because it is so pasay in WPF and you are referencing a property defined on your Window you could do something like below.
Background="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Color1}"

Resources