GuOrg / Gu.Wpf.DataGrid2D

Extension methods for WPF DataGrid enabling binding to T[,]
MIT License
155 stars 24 forks source link

Scientific Notation for Numeric Data #29

Open kaneorotar opened 6 years ago

kaneorotar commented 6 years ago

Thank you for this amazing user control. I'm currently trying to use it to display large numbers best represented in scientific notation in my project.

I have tried modifying your code by manually assigning StringFormat of Binding and ItemStringFormatProperty of ItemControl. But the format of the result stays the same.

Can anyone please point me to the right direction on how this can be implemented?

Thanks.

JohanLarsson commented 6 years ago
<DataGrid dataGrid2D:ItemsSource.Array2D="{Binding Data2D}"
          AutoGenerateColumns="False">
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding C0, StringFormat=F2}" Header="Col 1" />
    <DataGridTextColumn Binding="{Binding C1, StringFormat=F2}" Header="Col 2" />
  </DataGrid.Columns>
</DataGrid>

^ Seems to work, will not be much fun if the size is not fixed.

An alternative is to use the CellTemplate property like this:

<DataGrid dataGrid2D:ItemsSource.Array2D="{Binding Array2D}"
          IsReadOnly="True">
  <dataGrid2D:Cell.Template>
    <DataTemplate>
      <TextBlock Text="{Binding StringFormat=F2}" />
    </DataTemplate>
  </dataGrid2D:Cell.Template>
</DataGrid>

I'm not sure if DataGrid uses ItemStringFormat for anything. Maybe we can use it, what do you think @FoggyFinder?

FoggyFinder commented 6 years ago

I suppose you can set dataTemplate for cell:

<DataTemplate x:Key="CellTemplate">
    <TextBlock Text="{Binding Path=., StringFormat=E5}" />
</DataTemplate>
dataGrid2D:Cell.Template="{StaticResource CellTemplate}"

if column count is fluent

kaneorotar commented 6 years ago

@JohanLarsson @FoggyFinder Thank you very much for the replies.

I have tried both of your solutions and then realized that I forgot to mention that I also want to edit the cells and have TwoWay binding. My 2D data can also vary in size, which makes it unfavorable to pre-define the columns.

This enables me to edit the cells but doesn't update the source:

<DataTemplate x:Key="dg2DCellTemplate">
    <TextBox Text="{Binding Path=., StringFormat=0.000000E+00, Mode=TwoWay, BindsDirectlyToSource=True, UpdateSourceTrigger=LostFocus, NotifyOnSourceUpdated=True}" BorderBrush="{x:Null}" />
</DataTemplate>
...
<DataGrid dataGrid2D:ItemsSource.Array2D="{Binding Path=Outputs[0].Matrix, Mode=TwoWay}" ColumnWidth="*" dataGrid2D:Cell.Template="{StaticResource dg2DCellTemplate}" />

On the other hand, TwoWay binding works when I'm not using CellTemplate.

Can you please shed some light on this?

Thanks.

mennowo commented 6 years ago

Normally when using dataTemplates for a DataGrid, you will use two templates: one for displaying, one for editing. Maybe that would help? The 2D datagrid allows for this also. If I remember correctly:

dataGrid2D:Cell.Template="{StaticResource CellTemplate}"

dataGrid2D:Cell.EditingTemplate="{StaticResource CellEditingTemplate}"

On Sat, Mar 24, 2018 at 11:50 PM, Kan Wang notifications@github.com wrote:

@JohanLarsson https://github.com/JohanLarsson @FoggyFinder https://github.com/FoggyFinder Thank you very much for the replies.

I have tried both of your solutions and then realized that I forgot to mention that I also want to edit the cells and have TwoWay binding.

This enables me to edit the cells but doesn't update the source:

    <DataTemplate x:Key="dg2DCellTemplate">
        <TextBox Text="{Binding Path=., StringFormat=0.000000E+00, Mode=TwoWay, BindsDirectlyToSource=True, UpdateSourceTrigger=LostFocus, NotifyOnSourceUpdated=True}" BorderBrush="{x:Null}" />
    </DataTemplate>

Can you please shed some light on this?

Thanks.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/GuOrg/Gu.Wpf.DataGrid2D/issues/29#issuecomment-375930635, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpzEjYEEH4sBAESKKGQcq__q3EDX28nks5ths2zgaJpZM4S5epp .

-- To ensure safety and privacy, this email will selfdestruct in 5 seconds. Don't panic!

JohanLarsson commented 6 years ago

Looks like we have a bug. When using:

<DataGrid dataGrid2D:ItemsSource.Array2D="{Binding Array2D}">
    <dataGrid2D:Cell.Template>
        <DataTemplate>
            <TextBlock Text="{Binding StringFormat=E1}" />
        </DataTemplate>
    </dataGrid2D:Cell.Template>
    <dataGrid2D:Cell.EditingTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}" />
        </DataTemplate>
    </dataGrid2D:Cell.EditingTemplate>
</DataGrid>

It throws when entering edit mode.

mennowo commented 6 years ago

Strange! I use this all the time, never had any trouble. Though I always bind to properties on objects in a 2D array, not directly to those items themselves.

On Sun, Mar 25, 2018 at 1:30 PM, Johan Larsson notifications@github.com wrote:

Looks like we have a bug. When using:

It throws when entering edit mode.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/GuOrg/Gu.Wpf.DataGrid2D/issues/29#issuecomment-375963380, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpzEklKlgkNMkFbPFRcj84cvt1qFyUiks5th3_EgaJpZM4S5epp .

-- To ensure safety and privacy, this email will selfdestruct in 5 seconds. Don't panic!

odinsacred commented 6 years ago

Hello! Can anybody help me? I wanna bind 2D int array to DataGrid, but I don't understand how to create TwoWay binding. Now I'm use this code:

<DataGrid Grid.Column="1" Grid.Row="1" x:Name="AutoColumns"
    dataGrid2D:ItemsSource.Array2D="{Binding Path=Data2D, Mode=TwoWay}"
    dataGrid2D:ItemsSource.ColumnHeadersSource="{Binding ColumnHeaders}"
    dataGrid2D:ItemsSource.RowHeadersSource="{Binding RowHeaders}"
    ColumnWidth="50"
    SelectionUnit="Cell"
    IsReadOnly="False"
    IsEnabled="True">
<dataGrid2D:Cell.Template>
<DataTemplate>
    <TextBlock Text="{Binding Path=., StringFormat=X4}" IsEnabled="true"/>
</DataTemplate>
</dataGrid2D:Cell.Template>
    <dataGrid2D:Cell.EditingTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Path=., StringFormat=X4}" />
    </DataTemplate>
</dataGrid2D:Cell.EditingTemplate>
</DataGrid>

Also I'm tried to add an attributes like "Mode=TwoWay, BindsDirectlyToSource=True, UpdateSourceTrigger=LostFocus, NotifyOnSourceUpdated=True" In data templates, but it's do nothing effect. Now it's allow me to entering some numbers in cells, but not save to my array. And one detail - everything work good without templates, but I need them.

FoggyFinder commented 6 years ago

@odinsacred there is no "standard" way, but I suppose you can use converter for your collection (so it will be inner wrapper)

JohanLarsson commented 6 years ago

@FoggyFinder Maybe we should add an ObservableArray2D<T> that wraps a T[,]? This use case seems pretty common.

FoggyFinder commented 6 years ago

Maybe we should add an ObservableArray2D that wraps a T[,]?

@JohanLarsson Maybe. I was thinking about how better to handle this case, but all my options has some limitations, so I decided that simple converter is better.

FoggyFinder commented 6 years ago

for history

https://github.com/GuOrg/Gu.Wpf.DataGrid2D/issues/32

https://github.com/GuOrg/Gu.Wpf.DataGrid2D/issues/33