6

I have a WPF Datagrid in my application where I set the value of the ItemSource to the DefaultView of a DataTable that I have constructed. The problem lies in the fact that whenever I set the ColumnName of one of the columns in my DataTable to a string that includes '/' the header shows up in the DataGrid control but the values do not. How can I get around this?

enter image description here

This is the same table with the '/' replaced with '-' enter image description here

as an aside this also appears to happen with headers that have a '.' in them. So any decimal will cause the same behavior.

My grid is defined as

<DataGrid x:Name="dgLFKPI" />

and I am setting the value in code behind (yes it should be in a viewmodel and MVVM but it is a legacy app that is slowly moving that way).

dgLFKPI.ItemsSource = dt.DefaultView;
PlTaylor
  • 7,345
  • 11
  • 52
  • 94
  • 1
    Can you show your grid definition? – crthompson Jul 29 '14 at 14:16
  • Please see if this link helps you: http://msdn.microsoft.com/en-us/library/ms744986(v=vs.110).aspx. Also see, http://stackoverflow.com/questions/6720285/how-do-i-escape-a-slash-character-in-a-wpf-binding-path-or-how-to-work-around – S2S2 Jul 29 '14 at 14:18
  • @VS1 I have tried replacing the '/' with several versions of escape characters to no avail. Do you have a specific thing I should try? – PlTaylor Jul 29 '14 at 14:26
  • 1
    You could try to use characters that are similar to '/' - http://www.fileformat.info/info/unicode/char/2215/index.htm or http://www.fileformat.info/info/unicode/char/2044/index.htm. It may fool the WPF engine. – Eugene Podskal Jul 29 '14 at 14:29
  • 2
    Does [this solution](http://stackoverflow.com/a/15553960/302677) of using the AutoGeneratingColumn event to manually generate the binding for those special cases work for you? (The accepted answer to that question also contains an good explanation as to why this happens) – Rachel Jul 29 '14 at 14:31
  • @EugenePodskal That does work. – PlTaylor Jul 29 '14 at 14:36
  • @Rachel This works really nicely as well. If you make an answer of this I will mark it as the answer. – PlTaylor Jul 29 '14 at 14:36
  • Ahh, I was typing up my answer when Rachel posted that :( – Kcvin Jul 29 '14 at 14:37
  • @Rachel link also contains the proper escape sequence to handle any case with a '.' or '/' – PlTaylor Jul 29 '14 at 14:38
  • @PlTaylor, does this answer to use [] escape character does not work for you: http://stackoverflow.com/a/6724036/885920 – S2S2 Jul 29 '14 at 14:42
  • 1
    @VS1 ultimately it does. I was confused and trying to escape just the '/' and not the whole thing. i.e. "1 1[/]4" not "[1 1/4]". Rachel's answer was more comprehensive and explained it more thoroughly than the one you posted. – PlTaylor Jul 29 '14 at 14:46
  • @PlTaylor, Glad to know you found the solution. – S2S2 Jul 29 '14 at 14:48
  • Use a special symbol instead: U+2215: Division Slash: ∕ – Sergey Feb 15 '21 at 21:48

2 Answers2

5

The special characters in the column names are incorrectly parsed by the binding path parser.

So a column binding to 3/4 is actually only binding to the property 3, and not the property 3/4. (The same thing with the . binding)

You'll probably see binding errors in the debug window while this is running that should say the same sort of thing.

System.Windows.Data Error: 40 : BindingExpression path error: '3' property not found on 'object' ''DataRowView'

According to this answer

There are a number of different characters which have special meaning in a binding path including full stop ('.'), slash ('/'), square brackets ('[',']') and parenthesis ('(',')'), the parenthesis will cause your app to crash. These special characters can be escaped by surrounding the binding path with square brackets. More information about paths and character escaping can be found in the [Binding Declarations Overview][2]

That linked question also contains a good solution for dealing with grids that want to use auto-generated columns.

Use the AutoGeneratingColumn event, and manually create the bindings for columns with these special characters in their name to escape them using the square brackets.

<DataGrid x:Name="dgLFKPI"
          AutoGeneratingColumn="dgLFKPI_AutoGeneratingColumn" />
private void dgLFKPI_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyName.Contains('/') && e.Column is DataGridBoundColumn)
    {
        var col = e.Column as DataGridBoundColumn;
        col.Binding = new Binding(string.Format("[{0}]", e.PropertyName));
    }
}
Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
1

You need to set the columns specifically, then set the Header value of the column to your fraction value.

<DataGrid x:Name="dgLFKPI">
   <dg:DataGridTextColumn Header="0" Width="50" Binding="{Binding <columnname>}"  />
   <dg:DataGridTextColumn Header="1/4" Width="50" Binding="{Binding <columnname>}"  />
    ...
</DataGrid>

Alternatively, you could build it up in the codebehind:

var col = new DataGridTextColumn{
              Header = "1/4";
              Binding = new Binding("<columnname>")};
dataGrid1.Columns.Add(col);
crthompson
  • 15,653
  • 6
  • 58
  • 80
  • The problem with this method is my columns are generated dynamically. So I generate the DataTable dynamically and let the DataGrid display that. – PlTaylor Jul 29 '14 at 14:23
  • 1
    @PlTaylor, then i'd recommend doing it in the codebehind and looping your data columns. – crthompson Jul 29 '14 at 14:27