1
votes

I designed a project that has user defined controls with datagrids. Some columns of control's datagrid are DataGridTextColumn with twoway binding (to read and write data from/to binding model). Some cells of DataGridTextColumn contains very long text and can't be succesfully displayed in cell. I've decide to put scrollbars in this cells. Every cell column contains some user defined style, so I create my own with DataGridCell template replacment. Here it is:

<Style x:Key="DataGridTextColumnWithScrollBar" TargetType="{x:Type Control}" BasedOn="{StaticResource {x:Type wpf_toolkit:DataGridCell}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Control}">
                <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=TwoWay}">
                    <ContentPresenter.ContentTemplate>
                        <DataTemplate>
                            <TextBox Text="{Binding Path=Text, Mode=TwoWay}"
                                     TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" 
                                     VerticalAlignment="Stretch" Margin="2,0" BorderThickness="0"/>
                        </DataTemplate>
                    </ContentPresenter.ContentTemplate>
                </ContentPresenter>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Style DataGridTextColumnWithScrollBar merged with base datagrid text column cell style. It works fine, but I can't edit text(all scrolls appears, but after text was edited, model doesn't updates). Is there any solutions to resolve my problem? I tried many ways (for example, WPF Nested binding in a controltemplate) but nothing works...

P.S. I cannot change datagridtext column to datatemplate textcolumn because controls are stored in external dll library.

Thanks in advance.

2
perhaps you need to define two separate templates for cell template & cell edit template. using same for both may cause such issues. may you share some more code on how you use this template, we try to suggest some solution for you.pushpraj
I merge this style with default style what links to datagridtextcolumn cellstyle property. Can you show me examples of templates for cell template & cell edit template?ArhiChief
I have only this code <Style TargetType="{x:Type wpf_toolkit:DataGridTextColumn}"><-- Some styles --> <Setter Property="CellStyle" Value="{StaticResources DataGridTextColumnWithScrollBar}"/></Style>ArhiChief
which version of WPF Toolkit you are using?pushpraj
Version for .Net 3.5ArhiChief

2 Answers

1
votes

here is how you can resolve the issue

the style, note that i have removed the template and this style targets TextBox

    <Style x:Key="DataGridTextColumnWithScrollBar"
           TargetType="{x:Type TextBox}"
           BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="VerticalScrollBarVisibility"
                Value="auto" />
        <Setter Property="TextWrapping"
                Value="Wrap" />
        <Setter Property="VerticalAlignment"
                Value="Stretch" />
        <Setter Property="Margin"
                Value="2,0" />
        <Setter Property="BorderThickness"
                Value="0" />
    </Style>

then usage, instead of CellStyle use EditingElementStyle

    <wpf_toolkit:DataGridTextColumn Header="Some long text 2"
                                    Binding="{Binding SomeLongText1, Mode=TwoWay}"
                                    EditingElementStyle="{StaticResource DataGridTextColumnWithScrollBar}" />

if you want to style the normal view as well then add the following style

    <Style x:Key="DataGridTextBlockColumnWithWrap"
           TargetType="{x:Type TextBlock}"
           BasedOn="{StaticResource {x:Type TextBlock}}">
        <Setter Property="TextWrapping"
                Value="Wrap" />
        <Setter Property="VerticalAlignment"
                Value="Stretch" />
        <Setter Property="Margin"
                Value="2,0" />
    </Style>

use

    <wpf_toolkit:DataGridTextColumn Header="Some long text 2"
                                    Binding="{Binding SomeLongText1, Mode=TwoWay}"
                                    EditingElementStyle="{StaticResource DataGridTextColumnWithScrollBar}"
                                    ElementStyle="{StaticResource DataGridTextBlockColumnWithWrap}" />

you may use template to add scrollbar for non-edit mode as well


EDIT

as discussed here is a style based on trigger with explicit binding

    <Style x:Key="DataGridTextColumnWithScrollBar"
           TargetType="{x:Type wpf_toolkit:DataGridCell}"
           BasedOn="{StaticResource {x:Type wpf_toolkit:DataGridCell}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type wpf_toolkit:DataGridCell}">
                    <Grid Background="{TemplateBinding Background}">
                        <ScrollViewer VerticalScrollBarVisibility="Auto"
                                      x:Name="view">
                            <TextBlock Text="{Binding SomeLongText1}"
                                       TextWrapping="Wrap" />
                        </ScrollViewer>
                        <TextBox Text="{Binding SomeLongText1}"
                                 TextWrapping="Wrap"
                                 VerticalScrollBarVisibility="Auto"
                                 VerticalAlignment="Stretch"
                                 Margin="2,0"
                                 BorderThickness="0"
                                 x:Name="edit"
                                 Visibility="Collapsed" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEditing"
                                 Value="True">
                            <Setter Property="Visibility"
                                    TargetName="view"
                                    Value="Collapsed" />
                            <Setter Property="Visibility"
                                    TargetName="edit"
                                    Value="Visible" />
                        </Trigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

you can see that explicit binding is being used, so need to create style for every column. usage remains same, however since this is a custom template to get to edit mode you may need to press F2

or to be straight forward you can use

    <Style x:Key="DataGridTextColumnWithScrollBar"
           TargetType="{x:Type wpf_toolkit:DataGridCell}"
           BasedOn="{StaticResource {x:Type wpf_toolkit:DataGridCell}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type wpf_toolkit:DataGridCell}">
                    <TextBox Text="{Binding SomeLongText1}"
                             TextWrapping="Wrap"
                             VerticalScrollBarVisibility="Auto"
                             VerticalAlignment="Stretch"
                             Margin="2,0"
                             BorderThickness="0"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

but since there is no explicit edit mode this approach can cause data inconsistencies.

0
votes

The answer was very simple. Thanks for guys that gived answer here How to use TwoWay binding from within a UserControl? and here WPF TemplateBinding vs RelativeSource TemplatedParent

My problem solves by next code:

<Style x:Key="DataGridTextColumnWithScrollBar" TargetType="{x:Type wpf_toolkit:DataGridCell}" 
           BasedOn="{StaticResource {x:Type wpf_toolkit:DataGridCell}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type wpf_toolkit:DataGridCell}">
                    <TextBox Name="txtBox" Text="{Binding Content.Text,
                        RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                             VerticalScrollBarVisibility="Auto" TextWrapping="Wrap"
                             IsReadOnly="{TemplateBinding IsReadOnly}"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

So I can use it like this:

<wpf_toolkit:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items, Mode=TwoWay}"
                          RowStyle="{StaticResource DataGridRowMaxHeihgt }" ColumnWidth="*"
                          IsReadOnly="True">

        <wpf_toolkit:DataGrid.Columns>
            <wpf_toolkit:DataGridTextColumn Header="Some long text 2" IsReadOnly="True"
                                            Binding="{Binding SomeLongText1, Mode=TwoWay}"
                                            CellStyle="{StaticResource DataGridTextColumnWithScrollBar}"/>
            <wpf_toolkit:DataGridTextColumn Header="Some long text 2" 
                                            Binding="{Binding SomeLongText2, Mode=TwoWay}" IsReadOnly="False"
                                            CellStyle="{StaticResource DataGridTextColumnWithScrollBar}"/>
        </wpf_toolkit:DataGrid.Columns>
    </wpf_toolkit:DataGrid>

It makes all what i want.

P.S. Thanks for everyone for response.