This is a migrated thread and some comments may be shown as answers.

Adjusting row height automatically

7 Answers 127 Views
DataGrid
This is a migrated thread and some comments may be shown as answers.
David
Top achievements
Rank 1
David asked on 26 Mar 2018, 11:21 AM

I have a grid which incorporates Text columns, that I allow to user to edit. I use a Word Wrap for the TextBox, but the box in many (but not all) situations, overlaps the row itself, as shown in the attached Screen grab.

The XAML for the grid is as follows:

<tg:RadDataGrid x:Name="PaymentsGrid"
                RelativePanel.Below="spFinanceSummary1"
                IsEnabled="{x:Bind ViewModel.IsGrantEditingAllowed, Mode=TwoWay}"
                AutoGenerateColumns="False"
                IsSynchronizedWithCurrentItem="True"
                UserEditMode="Inline"
                Height="250" 
                ColumnDataOperationsMode="Inline"
                VerticalContentAlignment="Center"
                ItemsSource="{x:Bind ViewModel.OcPayments}"
                ScrollViewer.IsVerticalRailEnabled="True"
                extensions:ScrollViewerEx.VerticalScrollBarMargin="-20"
                Margin="0,20,0,0">
    <tg:RadDataGrid.Columns>
        <tg:DataGridTextColumn PropertyName="PayeeDetails"
                               Header="Payee details"
                               SizeMode="Fixed"
                               Width="250"
                               CanUserEdit="{x:Bind Mode=TwoWay, Path=ViewModel.IsFinanceEditingAllowed}">
            <tg:DataGridTextColumn.CellContentStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                    <Setter Property="TextWrapping" Value="Wrap"/>
                </Style>
            </tg:DataGridTextColumn.CellContentStyle>
            <tg:DataGridTextColumn.CellEditorStyle>
                <Style TargetType="TextBox">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                    <Setter Property="Width" Value="240"/>
                    <Setter Property="TextWrapping" Value="Wrap"/>
                </Style>
            </tg:DataGridTextColumn.CellEditorStyle>
        </tg:DataGridTextColumn>
        <tg:DataGridNumericalColumn PropertyName="Payment" Header="Amount"
                                    CellContentStyle="{StaticResource DefaultGridNumericStyle}"
                                    CellContentFormat="{}{0,0:C2}"
                                    SizeMode="Auto"
                                    tcp:CultureService.CultureName="en-GB"
                                    CanUserEdit="{x:Bind Mode=TwoWay, Path=ViewModel.IsFinanceEditingAllowed}">
            <tg:DataGridNumericalColumn.CellEditorStyle>
                <Style TargetType="tci:RadNumericBox">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                    <Setter Property="Maximum" Value="9999999999"/>
                    <Setter Property="ValueFormat" Value="{}{0,0:C2}"/>
                    <Setter Property="AllowNullValue" Value="False"/>
                    <Setter Property="ButtonsVisibility" Value="Collapsed"/>
                </Style>
            </tg:DataGridNumericalColumn.CellEditorStyle>
        </tg:DataGridNumericalColumn>
        <tg:DataGridDateColumn PropertyName="PaymentDate"
                               Header="Date"
                               CellContentFormat="{}{0,0:dd/MM/yyyy}"
                               Width="170"
                               SizeMode="Fixed"
                               CanUserEdit="{x:Bind Mode=TwoWay, Path=ViewModel.IsFinanceEditingAllowed}">
            <tg:DataGridDateColumn.CellEditorStyle>
                <Style TargetType="tci:RadDatePicker">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                    <Setter Property="Width" Value="150"/>
                    <Setter Property="SelectorOrder" Value="dmy"/>
                </Style>
 
            </tg:DataGridDateColumn.CellEditorStyle>
        </tg:DataGridDateColumn>
        <tg:DataGridTextColumn PropertyName="cStatus"
                               CanUserEdit="False"
                               Header="Status"
                               SizeMode="Auto"
                               IsVisible="{x:Bind Mode=TwoWay, Path=ViewModel.IsPaymentBeingViewed}"
                               />
        <tg:DataGridComboBoxColumn PropertyName="Status" Header="Status"
                                   ItemsSource="{x:Bind ViewModel.OcPaymentStatus}"
                                   DisplayMemberPath="Description"
                                   SelectedValuePath="Code"
                                   SizeMode="Auto"
                                   CanUserEdit="{x:Bind Mode=TwoWay, Path=ViewModel.IsFinanceEditingAllowed}"
                                   IsVisible="{x:Bind Mode=TwoWay, Path=ViewModel.IsPaymentBeingEdited}"/>
        <tg:DataGridTextColumn PropertyName="cMethod"
                               CanUserEdit="False"
                               Header="Method"
                               SizeMode="Auto"
                               IsVisible="{x:Bind Mode=TwoWay, Path=ViewModel.IsPaymentBeingViewed}"
                               />
        <tg:DataGridComboBoxColumn PropertyName="Method" Header="Method"
                                   ItemsSource="{x:Bind ViewModel.OcPaymentMethods}"
                                   DisplayMemberPath="Description"
                                   SelectedValuePath="Code"
                                   SizeMode="Auto"
                                   CanUserEdit="{x:Bind Mode=TwoWay, Path=ViewModel.IsFinanceEditingAllowed}"
                                   IsVisible="{x:Bind Mode=TwoWay, Path=ViewModel.IsPaymentBeingEdited}"/>
        <tg:DataGridBooleanColumn PropertyName="Requested" Header="Requested" SizeMode="Auto">
            <tg:DataGridBooleanColumn.CellEditorStyle>
                <Style TargetType="CheckBox">
                    <Setter Property="Margin" Value="48,5,0,5"/>
                    <Setter Property="MinWidth" Value="0"/>
                </Style>
            </tg:DataGridBooleanColumn.CellEditorStyle>
        </tg:DataGridBooleanColumn>
        <tg:DataGridBooleanColumn PropertyName="ReceiptReceived" Header="Receipt received" SizeMode="Auto">
            <tg:DataGridBooleanColumn.CellEditorStyle>
                <Style TargetType="CheckBox">
                    <Setter Property="Margin" Value="70,5,0,5"/>
                    <Setter Property="MinWidth" Value="0"/>
                </Style>
            </tg:DataGridBooleanColumn.CellEditorStyle>
        </tg:DataGridBooleanColumn>
        <tg:DataGridTextColumn PropertyName="ReasonCancelled"
                               Header="Notes"
                               SizeMode="Fixed"
                               Width="250">
            <tg:DataGridTextColumn.CellContentStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                    <Setter Property="TextWrapping" Value="Wrap"/>
                </Style>
            </tg:DataGridTextColumn.CellContentStyle>
            <tg:DataGridTextColumn.CellEditorStyle>
                <Style TargetType="TextBox">
                    <Setter Property="Margin" Value="5,5,5,5"/>
                    <Setter Property="Width" Value="240"/>
                </Style>
            </tg:DataGridTextColumn.CellEditorStyle>
        </tg:DataGridTextColumn>
    </tg:RadDataGrid.Columns>
    <tg:RadDataGrid.Commands>
        <gridCommands:DataGridUserCommand Id="CellTap" Command="{x:Bind Path=PaymentCellTap}"/>
        <gridCommands:DataGridUserCommand Id="BeginEdit" Command="{x:Bind Path=PaymentBeginEdit}"/>
        <gridCommands:DataGridUserCommand Id="CommitEdit" Command="{x:Bind Path=PaymentCommitEdit}"/>
        <gridCommands:DataGridUserCommand Id="CancelEdit" Command="{x:Bind Path=PaymentCancelEdit}"/>
    </tg:RadDataGrid.Commands>
</tg:RadDataGrid>

7 Answers, 1 is accepted

Sort by
0
Nasko
Telerik team
answered on 29 Mar 2018, 07:43 AM
Hello David,

Using the provided code-snippet I have tried to reproduce the observed by you behavior, but it seems everything is working as expected - when the Height of the column's editor changes the height of the row changes as well. Attached you can find the sample I have used for my investigation. Could you please, try to modify it in order to reproduce the issue and send it back - thus I will be able to continue investigating the issue and provide you with a prompt solution if possible?

I am looking forward to hearing from you.

Regards,
Nasko
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
David
Top achievements
Rank 1
answered on 29 Mar 2018, 09:36 AM

Thanks for your reply Nasko.

As I can see everything is fine in your example, and because the page of my project on which the XAML exhibits the overlapping behaviour is a lot more complex, I am instead going to try to reduce my page to the point where the overlapping stops and try to identify the cause by a process of elimination. This may take a little while, and am going on leave shortly so will get back to you in due course.

0
Nasko
Telerik team
answered on 30 Mar 2018, 07:32 AM
Hi David,

Take as much as time as you need to modify the sample in order to reproduce the issue. Meanwhile, if you have any additional questions or concerns, please do not hesitate to let me know.

Regards,
Nasko
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
David
Top achievements
Rank 1
answered on 10 Apr 2018, 02:33 PM

I have managed to replicate the behaviour I had identified in my datagrid. The Class I am using for the ObservableCollection datasource implements the INotifyPropertyChanged interface, and it is this which seems to cause the behaviour. I cannot seem to attach an update version of the sample, but the Data class is updated as follows (in my full data model, I also implement OnChanging and OnChanged events, but these don't seem to cause the issue. But if I comment out the OnPropertyChanged lines in the class, row sizing is again correct.

public class Data : global::System.ComponentModel.INotifyPropertyChanged
    {
        public string Country
        {
            get
            {
                return this._Country;
            }
            set
            {
                {
                    this._Country = value;
                    this.OnPropertyChanged("Country");
                }
            }
        }
        private string _Country;
        public string Capital
        {
            get
            {
                return this._Capital;
            }
            set
            {
                {
                    this._Capital = value;
                    this.OnPropertyChanged("Capital");
                }
            }
        }
        private string _Capital;
 
        public int Population
        {
            get
            {
                return this._Population;
            }
            set
            {
                {
                    this._Population = value;
                    this.OnPropertyChanged("Population");
                }
            }
        }
        private int _Population;
        public DateTime NationalHoliday
        {
            get
            {
                return this._NationalHoliday;
            }
            set
            {
                {
                    this._NationalHoliday = value;
                    this.OnPropertyChanged("NationalHoliday");
                }
            }
        }
        private DateTime _NationalHoliday;
 
        public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string property)
        {
            if ((this.PropertyChanged != null))
            {
                this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property));
            }
        }
    }
0
Accepted
Lance | Senior Manager Technical Support
Telerik team
answered on 12 Apr 2018, 08:59 PM
Hi David,

I noticed that you're not doing an equality evaluation before calling OnPropertyChanged. This means that you're going to cause a lot of unnecessary property rebinding. 

Here's your data model with the recommended use of property changed, along with a couple other tweaks to make it easier for you (i.e. CallerMemberName):

public class Data : INotifyPropertyChanged
{
    private string country;
    private string capital;
    private int population;
    private DateTime nationalHoliday;
 
    public Data()
    {
             
    }
 
    public string Country
    {
        get
        {
            return country;
        }
        set
        {
            if (country == value)
                return;
 
            country = value;
            OnPropertyChanged();
        }
    }
    public string Capital
    {
        get
        {
            return capital;
        }
        set
        {
            if (capital == value)
                return;
 
            capital = value;
            OnPropertyChanged();
        }
    }
  
    public int Population
    {
        get
        {
            return population;
        }
        set
        {
            if (population == value)
                return;
 
            population = value;
            OnPropertyChanged();
        }
    }
    public DateTime NationalHoliday
    {
        get
        {
            return nationalHoliday;
        }
        set
        {
            if (nationalHoliday == value)
                return;
 
            nationalHoliday = value;
            OnPropertyChanged();
        }
    }
 
 
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}


Let us know how it goes.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
David
Top achievements
Rank 1
answered on 13 Apr 2018, 08:57 AM

Thanks very much Lance, that resolved the issue, and will effectively mean I can indeed us the grid in my application (and I will purchase the commercial support option). The data classes I have been using are generated automatically by the OData Connected Service extension, which I think is a little old now, although still works well for connecting to OData services. Fortunately they are Partial Classes, so I can incorporate these modifications where necessary.

0
Lance | Senior Manager Technical Support
Telerik team
answered on 13 Apr 2018, 02:40 PM
Hi David,

I'm happy to hear that the problem is fixed! I'm familiar with such code generators, they tend to play it safe and make the classes as simple as possible, but can lead to issues like this. Since I have a little better understanding of your scenario, I have another suggestion that you might want to try.

Instead of using INotifyPropertyChanged in every model class, just create a single "ObservableObject" base class that has the property changed implementation, but also a "SetProperty" method that does the equality evaluation for you. 

Here's what I mean:

using System.Runtime.CompilerServices;
 
public class ObservableObject : INotifyPropertyChanged
{
    protected bool SetProperty<T>(ref T backingStore, T value, [CallerMemberName]string propertyName = "", Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;
 
        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }
         
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

now your model classes can be as simple as this!

public class Data : ObservableObject
{
    private string country;
    private string capital;
    private int population;
    private DateTime nationalHoliday;
  
    public string Country
    {
        get => country;
        set => SetProperty(ref country, value);
    }
    public string Capital
    {
        get => capital;
        set => SetProperty(ref capital, value);
    }
   
    public int Population
    {
        get => population;
        set => SetProperty(ref population, value);
    }
    public DateTime NationalHoliday
    {
        get => nationalHoliday;
        set => SetProperty(ref nationalHoliday, value);
    }
}

If you have any further trouble, open a support ticket and attach the relevant files so that we can investigate directly (you can attach ZIP files to tickets).  A support ticket carries a guaranteed response from a support engineer within the ticket's timeframe. Although we do our best to monitor and answer forum posts, this is limited to available resources.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
DataGrid
Asked by
David
Top achievements
Rank 1
Answers by
Nasko
Telerik team
David
Top achievements
Rank 1
Lance | Senior Manager Technical Support
Telerik team
Share this question
or