Search code examples
wpfsilverlightdatagriddatatemplatewpfdatagrid

DataGridColumn Header content WPF


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

EDIT

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.

FINAL EDIT

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


Solution

  • 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>
    

    The DataGrid in the program!

    And then the resources in the typeof(StringLibrary)

    Resource File

    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.