I want to localize a presentation and I'm having a brain freeze on this one. I'm using a markup extension, so instead of having this:
<DataGridTextColumn Header="Number" Binding="{Binding Number}" Width="60" CellStyle="{StaticResource NumberStyle}" />
I want this:
<DataGridTextColumn Header="{Resx Key=Header_Number}" Binding="{Binding Number}" Width="60" CellStyle="{StaticResource NumberStyle}" />
where the markup, which is well tested, will just return the right text for the current culture. But it isn't working. I assume I need either a HeaderStyle or HeaderTemplate but...
What is the fix?
Cheers,
Berryl
By isn't working I mean it isn't returning the text "Number" while in English, and instead returning a default value (ie, "#Header_Number).
By is working, I mean that
<Label FontWeight="Bold" Grid.Row="0" Grid.Column="0" Content="{Resx Key=Label_Amount}"/>
returns "Amount" while in English.
My bad, this is really more a result of the fact that WPF data grid columns to not inherit the DataContext of their parent.
The markup extension has a ResxName property which I like to set once for the entire window:
resx:ResxProperty.Name="NMoneys.Presentation.Resources.AllocatorView"
Title="{Resx Key=Window_Title}"
But since the headers in the data grid aren't part of the visual tree (although it sure seems they should be!), I have to specifically put the name of the Resx again, as in
<DataGridTextColumn Header="{Resx ResxName=NMoneys.Presentation.Resources.AllocatorView, Key=ColumnHeader_Number}" Binding="{Binding Number}" Width="60" CellStyle="{StaticResource NumberStyle}" />
I've run into this before and seen a few techniques to forward the DC, but in this case it isn't worth the bother.
Cheers,
Berryl
I assume you have models representating your entities. What I've done is used data annotations. Here is the example. Edit: Provided MVVM classes with screenshots
Model
using System.ComponentModel.DataAnnotations;
using Silverlight.Infrastructure.Properties;
namespace Silverlight.Infrastructure.Models
{
public class Customer
{
[Display(ResourceType = typeof(Resources), Name = "CustomerIdHeader")]
public int Id { get; set; }
// There must be an entry CustomerNameHeader in the resources else it
// will throw an exception
[Display(ResourceType = typeof(Resources), Name = "CustomerNameHeader")]
public string Name { get; set; }
}
}
The header content will then automatically bind to the display of the property.
ViewModel
using Silverlight.Infrastructure.Models
namespace Silverlight.ModuleA.ViewModels
{
//Prism namespaces
public class CustomerViewModel : NotificationObject
{
public CustomerViewModel()
{
// service for my customers.
CustomeService customerService = new CustomerService();
Customers = customerService.GetCustomers()
}
public ObservableCollection<Customer> Customers {get;set;}
}
}
View
<UserControl>
<Grid x:Name="LayoutRoot">
<data:DataGrid x:Name="CustomerGrid" ItemsSource="{Binding Customers}" AutoGenerateColumns="False" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Binding="{Binding Id, Mode=TwoWay}" />
<data:DataGridTextColumn Binding="{Binding Name, Mode=TwoWay}"/>
<data:DataGridTextColumn Binding="{Binding Surname, Mode=TwoWay}"/>
<data:DataGridTextColumn Binding="{Binding Company, Mode=TwoWay}"/>
</data:DataGrid.Columns>
</data:DataGrid>
</Grid>
</UserControl>
And then the resources in the typeof(StringLibrary)
As you can see the Name of the display is equal to the ResourceKey in the resources file. I came up with the annotations first when about 2-3 weeks ago when I was developing and testing with XML. But things like AutoMapper can map your objects to pocos like these or you can even Use WCF RIA services and you can have similiar annotations. WCF RIA is actually the one who is using them, but I just use them in a different way.
There might be a few tricks here and there to accomplish this. But when you do, you really get an easy solution.
I hope I've provided enough information.