7
7
using Avalonia . Interactivity ;
8
8
using Avalonia . VisualTree ;
9
9
using Avalonia . Collections ;
10
- using Avalonia . Utilities ;
11
10
using System ;
12
11
using System . ComponentModel ;
13
12
using System . Linq ;
@@ -24,8 +23,6 @@ public abstract class DataGridColumn : AvaloniaObject
24
23
{
25
24
internal const int DATAGRIDCOLUMN_maximumWidth = 65536 ;
26
25
private const bool DATAGRIDCOLUMN_defaultIsReadOnly = false ;
27
-
28
- private DataGridLength ? _width ; // Null by default, null means inherit the Width from the DataGrid
29
26
private bool ? _isReadOnly ;
30
27
private double ? _maxWidth ;
31
28
private double ? _minWidth ;
@@ -39,6 +36,7 @@ public abstract class DataGridColumn : AvaloniaObject
39
36
private IBinding _clipboardContentBinding ;
40
37
private ControlTheme _cellTheme ;
41
38
private Classes _cellStyleClasses ;
39
+ private bool _setWidthInternalNoCallback ;
42
40
43
41
/// <summary>
44
42
/// Initializes a new instance of the <see cref="T:Avalonia.Controls.DataGridColumn" /> class.
@@ -214,6 +212,36 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
214
212
OwningGrid ? . OnColumnVisibleStateChanged ( this ) ;
215
213
NotifyPropertyChanged ( change . Property . Name ) ;
216
214
}
215
+ else if ( change . Property == WidthProperty )
216
+ {
217
+ if ( ! _settingWidthInternally )
218
+ {
219
+ InheritsWidth = false ;
220
+ }
221
+ if ( _setWidthInternalNoCallback == false )
222
+ {
223
+ var grid = OwningGrid ;
224
+ var width = ( change as AvaloniaPropertyChangedEventArgs < DataGridLength > ) . NewValue . Value ;
225
+ if ( grid != null )
226
+ {
227
+ var oldWidth = ( change as AvaloniaPropertyChangedEventArgs < DataGridLength > ) . OldValue . Value ;
228
+ if ( width . IsStar != oldWidth . IsStar )
229
+ {
230
+ SetWidthInternalNoCallback ( width ) ;
231
+ IsInitialDesiredWidthDetermined = false ;
232
+ grid . OnColumnWidthChanged ( this ) ;
233
+ }
234
+ else
235
+ {
236
+ Resize ( oldWidth , width , false ) ;
237
+ }
238
+ }
239
+ else
240
+ {
241
+ SetWidthInternalNoCallback ( width ) ;
242
+ }
243
+ }
244
+ }
217
245
}
218
246
219
247
@@ -549,48 +577,15 @@ public double MinWidth
549
577
}
550
578
}
551
579
580
+ public static readonly StyledProperty < DataGridLength > WidthProperty = AvaloniaProperty
581
+ . Register < DataGridColumn , DataGridLength > ( nameof ( Width )
582
+ , coerce : CoerceWidth
583
+ ) ;
584
+
552
585
public DataGridLength Width
553
586
{
554
- get
555
- {
556
- return
557
- _width ??
558
- OwningGrid ? . ColumnWidth ??
559
- // We don't have a good choice here because we don't want to make this property nullable, see DevDiv Bugs 196581
560
- DataGridLength . Auto ;
561
- }
562
- set
563
- {
564
- if ( ! _width . HasValue || _width . Value != value )
565
- {
566
- if ( ! _settingWidthInternally )
567
- {
568
- InheritsWidth = false ;
569
- }
570
-
571
- if ( OwningGrid != null )
572
- {
573
- DataGridLength width = CoerceWidth ( value ) ;
574
- if ( width . IsStar != Width . IsStar )
575
- {
576
- // If a column has changed either from or to a star value, we want to recalculate all
577
- // star column widths. They are recalculated during Measure based off what the value we set here.
578
- SetWidthInternalNoCallback ( width ) ;
579
- IsInitialDesiredWidthDetermined = false ;
580
- OwningGrid . OnColumnWidthChanged ( this ) ;
581
- }
582
- else
583
- {
584
- // If a column width's value is simply changing, we resize it (to the right only).
585
- Resize ( width . Value , width . UnitType , width . DesiredValue , width . DisplayValue , false ) ;
586
- }
587
- }
588
- else
589
- {
590
- SetWidthInternalNoCallback ( value ) ;
591
- }
592
- }
593
- }
587
+ get => this . GetValue ( WidthProperty ) ;
588
+ set => SetValue ( WidthProperty , value ) ;
594
589
}
595
590
596
591
/// <summary>
@@ -812,19 +807,34 @@ internal void EndCellEditInternal()
812
807
/// on the rest of the star columns. For pixel widths, the desired value is based on the pixel value.
813
808
/// For auto widths, the desired value is initialized as the column's minimum width.
814
809
/// </summary>
810
+ /// <param name="source"></param>
815
811
/// <param name="width">The DataGridLength to coerce.</param>
816
812
/// <returns>The resultant (coerced) DataGridLength.</returns>
817
- internal DataGridLength CoerceWidth ( DataGridLength width )
813
+ static DataGridLength CoerceWidth ( AvaloniaObject source , DataGridLength width )
818
814
{
815
+ var target = ( DataGridColumn ) source ;
816
+
817
+ if ( target . _setWidthInternalNoCallback )
818
+ {
819
+ return width ;
820
+ }
821
+
822
+ if ( ! target . IsSet ( WidthProperty ) )
823
+ {
824
+
825
+ return target . OwningGrid ? . ColumnWidth ??
826
+ DataGridLength . Auto ;
827
+ }
828
+
819
829
double desiredValue = width . DesiredValue ;
820
830
if ( double . IsNaN ( desiredValue ) )
821
831
{
822
- if ( width . IsStar && OwningGrid != null && OwningGrid . ColumnsInternal != null )
832
+ if ( width . IsStar && target . OwningGrid != null && target . OwningGrid . ColumnsInternal != null )
823
833
{
824
834
double totalStarValues = 0 ;
825
835
double totalStarDesiredValues = 0 ;
826
836
double totalNonStarDisplayWidths = 0 ;
827
- foreach ( DataGridColumn column in OwningGrid . ColumnsInternal . GetDisplayedColumns ( c => c . IsVisible && c != this && ! double . IsNaN ( c . Width . DesiredValue ) ) )
837
+ foreach ( DataGridColumn column in target . OwningGrid . ColumnsInternal . GetDisplayedColumns ( c => c . IsVisible && c != target && ! double . IsNaN ( c . Width . DesiredValue ) ) )
828
838
{
829
839
if ( column . Width . IsStar )
830
840
{
@@ -839,7 +849,7 @@ internal DataGridLength CoerceWidth(DataGridLength width)
839
849
if ( totalStarValues == 0 )
840
850
{
841
851
// Compute the new star column's desired value based on the available space if there are no other visible star columns
842
- desiredValue = Math . Max ( ActualMinWidth , OwningGrid . CellsWidth - totalNonStarDisplayWidths ) ;
852
+ desiredValue = Math . Max ( target . ActualMinWidth , target . OwningGrid . CellsWidth - totalNonStarDisplayWidths ) ;
843
853
}
844
854
else
845
855
{
@@ -853,7 +863,7 @@ internal DataGridLength CoerceWidth(DataGridLength width)
853
863
}
854
864
else
855
865
{
856
- desiredValue = ActualMinWidth ;
866
+ desiredValue = target . ActualMinWidth ;
857
867
}
858
868
}
859
869
@@ -862,7 +872,7 @@ internal DataGridLength CoerceWidth(DataGridLength width)
862
872
{
863
873
displayValue = desiredValue ;
864
874
}
865
- displayValue = Math . Max ( ActualMinWidth , Math . Min ( ActualMaxWidth , displayValue ) ) ;
875
+ displayValue = Math . Max ( target . ActualMinWidth , Math . Min ( target . ActualMaxWidth , displayValue ) ) ;
866
876
867
877
return new DataGridLength ( width . Value , width . UnitType , desiredValue , displayValue ) ;
868
878
}
@@ -896,7 +906,7 @@ internal virtual DataGridColumnHeader CreateHeader()
896
906
} ;
897
907
result [ ! ContentControl . ContentProperty ] = this [ ! HeaderProperty ] ;
898
908
result [ ! ContentControl . ContentTemplateProperty ] = this [ ! HeaderTemplateProperty ] ;
899
- if ( OwningGrid . ColumnHeaderTheme is { } columnTheme )
909
+ if ( OwningGrid . ColumnHeaderTheme is { } columnTheme )
900
910
{
901
911
result . SetValue ( StyledElement . ThemeProperty , columnTheme , BindingPriority . Template ) ;
902
912
}
@@ -909,7 +919,7 @@ internal virtual DataGridColumnHeader CreateHeader()
909
919
/// </summary>
910
920
internal void EnsureWidth ( )
911
921
{
912
- SetWidthInternalNoCallback ( CoerceWidth ( Width ) ) ;
922
+ SetWidthInternalNoCallback ( CoerceWidth ( this , Width ) ) ;
913
923
}
914
924
915
925
internal Control GenerateElementInternal ( DataGridCell cell , object dataItem )
@@ -931,17 +941,17 @@ internal object PrepareCellForEditInternal(Control editingElement, RoutedEventAr
931
941
/// can only decrease in size by the amount that the columns after it can increase in size.
932
942
/// Likewise, the column can only increase in size if other columns can spare the width.
933
943
/// </summary>
934
- /// <param name="value">The new Value.</param>
935
- /// <param name="unitType">The new UnitType.</param>
936
- /// <param name="desiredValue">The new DesiredValue.</param>
937
- /// <param name="displayValue">The new DisplayValue.</param>
944
+ /// <param name="oldWidth">with before resize.</param>
945
+ /// <param name="newWidth">with after resize.</param>
938
946
/// <param name="userInitiated">Whether or not this resize was initiated by a user action.</param>
939
- internal void Resize ( double value , DataGridLengthUnitType unitType , double desiredValue , double displayValue , bool userInitiated )
947
+
948
+ // double value, DataGridLengthUnitType unitType, double desiredValue, double displayValue
949
+ internal void Resize ( DataGridLength oldWidth , DataGridLength newWidth , bool userInitiated )
940
950
{
941
- double newValue = value ;
942
- double newDesiredValue = desiredValue ;
943
- double newDisplayValue = Math . Max ( ActualMinWidth , Math . Min ( ActualMaxWidth , displayValue ) ) ;
944
- DataGridLengthUnitType newUnitType = unitType ;
951
+ double newValue = newWidth . Value ;
952
+ double newDesiredValue = newWidth . DesiredValue ;
953
+ double newDisplayValue = Math . Max ( ActualMinWidth , Math . Min ( ActualMaxWidth , newWidth . DisplayValue ) ) ;
954
+ DataGridLengthUnitType newUnitType = newWidth . UnitType ;
945
955
946
956
int starColumnsCount = 0 ;
947
957
double totalDisplayWidth = 0 ;
@@ -955,11 +965,11 @@ internal void Resize(double value, DataGridLengthUnitType unitType, double desir
955
965
956
966
// If we're using star sizing, we can only resize the column as much as the columns to the
957
967
// right will allow (i.e. until they hit their max or min widths).
958
- if ( ! hasInfiniteAvailableWidth && ( starColumnsCount > 0 || ( unitType == DataGridLengthUnitType . Star && Width . IsStar && userInitiated ) ) )
968
+ if ( ! hasInfiniteAvailableWidth && ( starColumnsCount > 0 || ( newUnitType == DataGridLengthUnitType . Star && newWidth . IsStar && userInitiated ) ) )
959
969
{
960
- double limitedDisplayValue = Width . DisplayValue ;
970
+ double limitedDisplayValue = oldWidth . DisplayValue ;
961
971
double availableIncrease = Math . Max ( 0 , OwningGrid . CellsWidth - totalDisplayWidth ) ;
962
- double desiredChange = newDisplayValue - Width . DisplayValue ;
972
+ double desiredChange = newDisplayValue - oldWidth . DisplayValue ;
963
973
if ( desiredChange > availableIncrease )
964
974
{
965
975
// The desired change is greater than the amount of available space,
@@ -979,7 +989,7 @@ internal void Resize(double value, DataGridLengthUnitType unitType, double desir
979
989
// The desired change is negative, so we need to increase the widths of columns to the right.
980
990
limitedDisplayValue += desiredChange + OwningGrid . IncreaseColumnWidths ( DisplayIndex + 1 , - desiredChange , userInitiated ) ;
981
991
}
982
- if ( ActualCanUserResize || ( Width . IsStar && ! userInitiated ) )
992
+ if ( ActualCanUserResize || ( oldWidth . IsStar && ! userInitiated ) )
983
993
{
984
994
newDisplayValue = limitedDisplayValue ;
985
995
}
@@ -1002,9 +1012,10 @@ internal void Resize(double value, DataGridLengthUnitType unitType, double desir
1002
1012
}
1003
1013
}
1004
1014
1005
- DataGridLength oldWidth = Width ;
1006
- SetWidthInternalNoCallback ( new DataGridLength ( Math . Min ( double . MaxValue , newValue ) , newUnitType , newDesiredValue , newDisplayValue ) ) ;
1007
- if ( Width != oldWidth )
1015
+ newDisplayValue = Math . Min ( double . MaxValue , newValue ) ;
1016
+ newWidth = new DataGridLength ( newDisplayValue , newUnitType , newDesiredValue , newDisplayValue ) ;
1017
+ SetWidthInternalNoCallback ( newWidth ) ;
1018
+ if ( newWidth != oldWidth )
1008
1019
{
1009
1020
OwningGrid . OnColumnWidthChanged ( this ) ;
1010
1021
}
@@ -1052,7 +1063,17 @@ internal void SetWidthInternal(DataGridLength width)
1052
1063
/// <param name="width">The new Width.</param>
1053
1064
internal void SetWidthInternalNoCallback ( DataGridLength width )
1054
1065
{
1055
- _width = width ;
1066
+ var originalValue = _setWidthInternalNoCallback ;
1067
+ _setWidthInternalNoCallback = true ;
1068
+ try
1069
+ {
1070
+ Width = width ;
1071
+ }
1072
+ finally
1073
+ {
1074
+ _setWidthInternalNoCallback = originalValue ;
1075
+ }
1076
+
1056
1077
}
1057
1078
1058
1079
/// <summary>
@@ -1122,7 +1143,7 @@ internal DataGridSortDescription GetSortDescription()
1122
1143
&& OwningGrid . DataConnection != null
1123
1144
&& OwningGrid . DataConnection . SortDescriptions != null )
1124
1145
{
1125
- if ( CustomSortComparer != null )
1146
+ if ( CustomSortComparer != null )
1126
1147
{
1127
1148
return
1128
1149
OwningGrid . DataConnection . SortDescriptions
0 commit comments