diff --git a/src/Microsoft.DotNet.Wpf/cycle-breakers/PresentationFramework/PresentationFramework.cs b/src/Microsoft.DotNet.Wpf/cycle-breakers/PresentationFramework/PresentationFramework.cs index 78efe1b3984..8558f3f0896 100644 --- a/src/Microsoft.DotNet.Wpf/cycle-breakers/PresentationFramework/PresentationFramework.cs +++ b/src/Microsoft.DotNet.Wpf/cycle-breakers/PresentationFramework/PresentationFramework.cs @@ -5036,6 +5036,24 @@ public void Refresh() { } public override bool ShouldSerializeContent() { throw null; } public void StopLoading() { } } + internal partial class ColumnDefinitionCollectionConverter : System.ComponentModel.TypeConverter + { + internal ColumnDefinitionCollectionConverter() { } + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Type sourceType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) { throw null; } + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Globalization.CultureInfo cultureInfo, object source) { throw null; } + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + } + + internal partial class RowDefinitionCollectionConverter : System.ComponentModel.TypeConverter + { + internal RowDefinitionCollectionConverter() { } + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Type sourceType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) { throw null; } + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Globalization.CultureInfo cultureInfo, object source) { throw null; } + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + } + public partial class Grid : System.Windows.Controls.Panel, System.Windows.Markup.IAddChild { public static readonly System.Windows.DependencyProperty ColumnProperty; @@ -5045,9 +5063,11 @@ public partial class Grid : System.Windows.Controls.Panel, System.Windows.Markup public static readonly System.Windows.DependencyProperty RowSpanProperty; public static readonly System.Windows.DependencyProperty ShowGridLinesProperty; public Grid() { } + [System.ComponentModel.TypeConverterAttribute(typeof(System.Windows.Controls.ColumnDefinitionCollectionConverter))] [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Content)] public System.Windows.Controls.ColumnDefinitionCollection ColumnDefinitions { get { throw null; } } protected internal override System.Collections.IEnumerator LogicalChildren { get { throw null; } } + [System.ComponentModel.TypeConverterAttribute(typeof(System.Windows.Controls.RowDefinitionCollectionConverter))] [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Content)] public System.Windows.Controls.RowDefinitionCollection RowDefinitions { get { throw null; } } public bool ShowGridLines { get { throw null; } set { } } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj index 6e84493822b..031bbf308c1 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj @@ -547,6 +547,7 @@ + @@ -739,6 +740,7 @@ + diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs index 6962180fe76..af42b0acb58 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs @@ -562,7 +562,7 @@ private void PrivateValidateValueForAddition(object value) throw new ArgumentException(SR.Format(SR.GridCollection_MustBeCertainType, "ColumnDefinitionCollection", "ColumnDefinition")); } - if (item.Parent != null) + if (item.Parent != _owner && item.Parent != null) { throw new ArgumentException(SR.Format(SR.GridCollection_InOtherCollection, "value", "ColumnDefinitionCollection")); } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinitionCollectionConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinitionCollectionConverter.cs new file mode 100644 index 00000000000..87cba0167d4 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinitionCollectionConverter.cs @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.Windows.Controls; +using System.Windows.Markup; +using System.Globalization; + +#pragma warning disable 1634, 1691 // suppressing PreSharp warnings + +namespace System.Windows.Controls +{ + + internal class ColumnDefinitionCollectionConverter : TypeConverter + { + #region Public Methods + + /// + /// CanConvertFrom - Returns whether or not this class can convert from a given type. + /// + /// + /// bool - True if thie converter can convert from the provided type, false if not. + /// + /// The ITypeDescriptorContext for this call. + /// The Type being queried for support. + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + /// + /// CanConvertTo - Returns whether or not this class can convert to a given type. + /// + /// + /// bool - True if this converter can convert to the provided type, false if not. + /// + /// The ITypeDescriptorContext for this call. + /// The Type being queried for support. + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); + } + + /// + /// ConvertFrom - Attempt to convert to a ColumnDefinitionCollection from the given object. + /// + /// + /// The object which was constructoed. + /// + /// + /// An ArgumentNullException is thrown if the example object is null. + /// + /// The ITypeDescriptorContext for this call. + /// The CultureInfo which is respected when converting. + /// The Thickness to convert. + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if(value != null) + { + if (value is string input) + { + IProvideValueTarget ipvt = context?.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; + Grid grid = ipvt?.TargetObject as Grid; + if(grid != null) + { + var collection = new ColumnDefinitionCollection(grid); // Pass Grid instance + var converter = new GridLengthConverter(); + + if(input == ""){ + return collection; + } + foreach (var length in input.Split(',')) + { + if (converter.ConvertFromString(length.Trim()) is GridLength gridLength) + { + collection.Add(new ColumnDefinition { Width = gridLength }); + } + } + return collection; + } + } + return base.ConvertFrom(context, culture, value); + } + throw GetConvertFromException(value); + } + + /// + /// ConvertTo - Attempt to convert a ColumnDefinitionCollection to the given type + /// + /// + /// The object which was constructoed. + /// + /// + /// An ArgumentNullException is thrown if the example object is null. + /// + /// The ITypeDescriptorContext for this call. + /// The CultureInfo which is respected when converting. + /// The ColumnDefintionCollection to convert. + /// The type to which to convert the ColumnDefintionCollection instance. + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + ArgumentNullException.ThrowIfNull(value); + ArgumentNullException.ThrowIfNull(destinationType); + if (destinationType == typeof(string) && value is ColumnDefinitionCollection columnDefinitions) + { + var parts = new string[columnDefinitions.Count]; + + for (int i = 0; i < columnDefinitions.Count; i++) + { + parts[i] = columnDefinitions[i].Width.ToString(); + } + + return string.Join(",", parts); + } + + return base.ConvertTo(context, culture, value, destinationType); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Grid.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Grid.cs index 7e7a8040c82..99fab6bf0a2 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Grid.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Grid.cs @@ -31,7 +31,6 @@ using System.Windows.Documents; using System.Windows.Media; using System.Windows.Markup; - #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.Windows.Controls @@ -272,6 +271,7 @@ public bool ShowGridLines /// /// Returns a ColumnDefinitionCollection of column definitions. /// + [TypeConverter(typeof(ColumnDefinitionCollectionConverter))] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ColumnDefinitionCollection ColumnDefinitions { @@ -287,6 +287,7 @@ public ColumnDefinitionCollection ColumnDefinitions /// /// Returns a RowDefinitionCollection of row definitions. /// + [TypeConverter(typeof(RowDefinitionCollectionConverter))] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public RowDefinitionCollection RowDefinitions { diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinition.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinition.cs index b50920ea489..34621c1c87b 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinition.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinition.cs @@ -562,7 +562,7 @@ private void PrivateValidateValueForAddition(object value) throw new ArgumentException(SR.Format(SR.GridCollection_MustBeCertainType, "RowDefinitionCollection", "RowDefinition")); } - if (item.Parent != null) + if (item.Parent != _owner && item.Parent != null) { throw new ArgumentException(SR.Format(SR.GridCollection_InOtherCollection, "value", "RowDefinitionCollection")); } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinitionCollectionConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinitionCollectionConverter.cs new file mode 100644 index 00000000000..81fbe3fcdc4 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RowDefinitionCollectionConverter.cs @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.Windows.Controls; +using System.Windows.Markup; +using System.Globalization; + +#pragma warning disable 1634, 1691 // suppressing PreSharp warnings + +namespace System.Windows.Controls +{ + + internal class RowDefinitionCollectionConverter : TypeConverter + { + #region Public Methods + + /// + /// CanConvertFrom - Returns whether or not this class can convert from a given type. + /// + /// + /// bool - True if thie converter can convert from the provided type, false if not. + /// + /// The ITypeDescriptorContext for this call. + /// The Type being queried for support. + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + /// + /// CanConvertTo - Returns whether or not this class can convert to a given type. + /// + /// + /// bool - True if this converter can convert to the provided type, false if not. + /// + /// The ITypeDescriptorContext for this call. + /// The Type being queried for support. + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); + } + + /// + /// ConvertFrom - Attempt to convert to a RowDefinitionCollection from the given object. + /// + /// + /// The object which was constructoed. + /// + /// + /// An ArgumentNullException is thrown if the example object is null. + /// + /// + /// An ArgumentException is thrown if the object is not null and is not a valid type, + /// or if the destinationType isn't one of the valid destination types. + /// + /// The ITypeDescriptorContext for this call. + /// The CultureInfo which is respected when converting. + /// The Thickness to convert. + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if(value != null){ + if (value is string input) + { + IProvideValueTarget ipvt = context?.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; + Grid grid = ipvt?.TargetObject as Grid; + if(grid != null) + { + var collection = new RowDefinitionCollection(grid); // Pass Grid instance + var converter = new GridLengthConverter(); + + if(input == ""){ + return collection; + } + foreach (var length in input.Split(',')) + { + if (converter.ConvertFromString(length.Trim()) is GridLength gridLength) + { + collection.Add(new RowDefinition { Height = gridLength }); + } + } + return collection; + } + } + return base.ConvertFrom(context, culture, value); + } + throw GetConvertFromException(value); + } + + /// + /// ConvertTo - Attempt to convert a RowDefinitionCollection to the given type + /// + /// + /// The object which was constructoed. + /// + /// + /// An ArgumentNullException is thrown if the example object is null. + /// + /// The ITypeDescriptorContext for this call. + /// The CultureInfo which is respected when converting. + /// The RowDefintionCollection to convert. + /// The type to which to convert the RowDefintionCollection instance. + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + ArgumentNullException.ThrowIfNull(value); + ArgumentNullException.ThrowIfNull(destinationType); + if (destinationType == typeof(string) && value is RowDefinitionCollection RowDefinitions) + { + var parts = new string[RowDefinitions.Count]; + + for (int i = 0; i < RowDefinitions.Count; i++) + { + parts[i] = RowDefinitions[i].Height.ToString(); + } + + return string.Join(",", parts); + } + + return base.ConvertTo(context, culture, value, destinationType); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/WpfGeneratedKnownProperties.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/WpfGeneratedKnownProperties.cs index 2fd51dff509..01a047466b4 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/WpfGeneratedKnownProperties.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/WpfGeneratedKnownProperties.cs @@ -6403,7 +6403,16 @@ private WpfKnownMember Create_BamlProperty_Grid_ColumnDefinitions() false // IsAttachable ); bamlMember.GetDelegate = delegate(object target) { return ((System.Windows.Controls.Grid)target).ColumnDefinitions; }; + bamlMember.SetDelegate = delegate(object target, object value) { + System.Windows.Controls.ColumnDefinitionCollection columns = ((System.Windows.Controls.Grid)target).ColumnDefinitions; + columns.Clear(); + foreach(System.Windows.Controls.ColumnDefinition column in (System.Windows.Controls.ColumnDefinitionCollection)value) + { + columns.Add(column); + } + }; bamlMember.IsWritePrivate = true; + bamlMember.TypeConverterType = typeof(System.Windows.Controls.ColumnDefinitionCollectionConverter); bamlMember.Freeze(); return bamlMember; } @@ -6420,7 +6429,16 @@ private WpfKnownMember Create_BamlProperty_Grid_RowDefinitions() false // IsAttachable ); bamlMember.GetDelegate = delegate(object target) { return ((System.Windows.Controls.Grid)target).RowDefinitions; }; + bamlMember.SetDelegate = delegate(object target, object value) { + System.Windows.Controls.RowDefinitionCollection rows = ((System.Windows.Controls.Grid)target).RowDefinitions; + rows.Clear(); + foreach(System.Windows.Controls.RowDefinition row in (System.Windows.Controls.RowDefinitionCollection)value) + { + rows.Add(row); + } + }; bamlMember.IsWritePrivate = true; + bamlMember.TypeConverterType = typeof(System.Windows.Controls.RowDefinitionCollectionConverter); bamlMember.Freeze(); return bamlMember; } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlReaderHelper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlReaderHelper.cs index 4ce11585b23..20367fe4434 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlReaderHelper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlReaderHelper.cs @@ -3196,7 +3196,14 @@ private void WritePropertyAttribute( bool propertyCanWrite; if (propInfo != null) { - propertyCanWrite = propInfo.CanWrite; + if(propInfo.Name == "ColumnDefinitions" || propInfo.Name == "RowDefinitions") + { + propertyCanWrite = true; + } + else + { + propertyCanWrite = propInfo.CanWrite; + } } #if !PBTCOMPILER else if (dynamicObject is DependencyProperty && @@ -3231,7 +3238,7 @@ private void WritePropertyAttribute( } } - if (propInfo != null && !XamlTypeMapper.IsAllowedPropertySet(propInfo)) + if (propInfo != null && propInfo.Name != "ColumnDefinitions" && propInfo.Name != "RowDefinitions" && !XamlTypeMapper.IsAllowedPropertySet(propInfo)) { ThrowException(nameof(SR.ParserCantSetAttribute), "property", $"{declaringType.Name}.{attribLocalName}", "set"); } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs index 15b0071ed2d..e482dc69d34 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/ref/PresentationFramework.cs @@ -5106,6 +5106,25 @@ public void Refresh() { } public override bool ShouldSerializeContent() { throw null; } public void StopLoading() { } } + + internal partial class ColumnDefinitionCollectionConverter : System.ComponentModel.TypeConverter + { + internal ColumnDefinitionCollectionConverter() { } + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Type sourceType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) { throw null; } + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Globalization.CultureInfo cultureInfo, object source) { throw null; } + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + } + + internal partial class RowDefinitionCollectionConverter : System.ComponentModel.TypeConverter + { + internal RowDefinitionCollectionConverter() { } + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Type sourceType) { throw null; } + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) { throw null; } + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext typeDescriptorContext, System.Globalization.CultureInfo cultureInfo, object source) { throw null; } + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + } + public partial class Grid : System.Windows.Controls.Panel, System.Windows.Markup.IAddChild { public static readonly System.Windows.DependencyProperty ColumnProperty; @@ -5115,9 +5134,11 @@ public partial class Grid : System.Windows.Controls.Panel, System.Windows.Markup public static readonly System.Windows.DependencyProperty RowSpanProperty; public static readonly System.Windows.DependencyProperty ShowGridLinesProperty; public Grid() { } + [System.ComponentModel.TypeConverterAttribute(typeof(System.Windows.Controls.ColumnDefinitionCollectionConverter))] [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Content)] public System.Windows.Controls.ColumnDefinitionCollection ColumnDefinitions { get { throw null; } } protected internal override System.Collections.IEnumerator LogicalChildren { get { throw null; } } + [System.ComponentModel.TypeConverterAttribute(typeof(System.Windows.Controls.RowDefinitionCollectionConverter))] [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Content)] public System.Windows.Controls.RowDefinitionCollection RowDefinitions { get { throw null; } } public bool ShowGridLines { get { throw null; } set { } }