如何使转换为 GridLength 与 GridUnitType.Star 一起使用?
How to make the converted to GridLength work with GridUnitType.Star?
我在尝试将双精度转换为星型单位的 GridLength 时出错。转换后的本身工作正常,但我在运行时遇到错误
"System.ArgumentException: NaN is not a valid value for width\n at Xamarin.Forms.Size..ctor (System.Double width, System.Double height) [0x00008] in D:\a\s\Xamarin.Forms.Core\Size.cs:19 \n at Xamarin.Forms.Grid.ContractColumnsIfNeeded (System.Double width, System.Func`2[T,TResult] predicate) [0x00075] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:213 \n at Xamarin.Forms.Grid.MeasureAndContractStarredColumns (System.Double width, System.Double height, System.Double totalStarsWidth) [0x000bb] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:397 \n at Xamarin.Forms.Grid.MeasureGrid (System.Double width, System.Double height, System.Boolean requestSize) [0x0010e] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:509 \n at Xamarin.Forms.Grid.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0002a] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:58 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\
\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.Grid.MeasureStarredRows () [0x000c3] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:548 \n at Xamarin.Forms.Grid.MeasureAndContractStarredRows (System.Double width, System.Double height, System.Double totalStarsHeight) [0x00000] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:403 \n at Xamarin.Forms.Grid.MeasureGrid (System.Double width, System.Double height, System.Boolean requestSize) [0x0011
7] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:510 \n at Xamarin.Forms.Grid.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0002a] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:58 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.StackLayout.CalculateNaiveLayout (Xamarin.Forms.Stac
kLayout+LayoutInformation layout, Xamarin.Forms.StackOrientation orientation, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint) [0x000a8] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:163 \n at Xamarin.Forms.StackLayout.CalculateLayout (Xamarin.Forms.StackLayout+LayoutInformation layout, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint, System.Boolean processExpanders) [0x00058] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:123 \n at Xamarin.Forms.StackLayout.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00019] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:80 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\
s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.Grid.CalculateAutoCells (System.Double width, System.Double height) [0x000e5] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:131 \n at Xamarin.Forms.Grid.MeasureGrid (System.Double width, System.Double height, System.Boolean requestSize) [0x0000c] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:483 \n at Xamarin.Forms.Grid.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0002a] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:58 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000]
in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.ScrollView.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0005d] in D:\a\s\Xamarin.Forms.Core\ScrollView.cs:233 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Dou
ble widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.StackLayout.CalculateNaiveLayout (Xamarin.Forms.StackLayout+LayoutInformation layout, Xamarin.Forms.StackOrientation orientation, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint) [0x000a8] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:163 \n at Xamarin.Forms.StackLayout.CalculateLayout (Xamarin.Forms.StackLayout+LayoutInformation layout, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint, System.Boolean pro
cessExpanders) [0x00058] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:123 \n at Xamarin.Forms.StackLayout.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0005b] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:57 \n at Xamarin.Forms.Layout.UpdateChildrenLayout () [0x0014b] in D:\a\s\Xamarin.Forms.Core\Layout.cs:263 \n at Xamarin.Forms.Layout.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:223 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.L
ayout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x001da] in D:\a\s\Xamarin.Forms.Core\Layout.cs:177 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0010d] in D:\a\s\Xamarin.Forms.Core\Page.cs:187 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualEleme
nt.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x0005f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:146 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0010d] in D:\a\s\Xamarin.Forms.Core\Page.cs:187 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\
1\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x0005f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:146 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0010d] in D:\a\s\Xamarin.Forms.Core\Page.cs:187 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, Sy
stem.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x0005f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:146 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x00103] in D:\a\s\Xamarin.Forms.C
ore\Page.cs:185 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Platform.iOS.NavigationRenderer.ViewDidLayoutSubviews () [0x00172] in D:\a\s\Xamarin.Forms.Platform.iOS\Renderers\NavigationRe
nderer.cs:182 \n at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)\n at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.4.0.64/src/Xamarin.iOS/UIKit/UIApplication.cs:79 \n at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0002c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.4.0.64/src/Xamarin.iOS/UIKit/UIApplication.cs:63 \n at PrenCare.iOS.Application.Main (System.String[] args) [0x00002] in C:\Users\ondre\source\repos\PrenCare\src\Version02\PrenCare\PrenCare.iOS\Main.cs:19 "
。奇怪的是,当我使用绝对单位时,转换器工作得很好。
转换器
public class NumberToGridLengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is double numberValue))
{
throw new Exception($"Type {value.GetType().FullName} cannot be converted to GridLenght");
}
return new GridLength(numberValue, GridUnitType.Star); // Star makes it crash
//return GridLength.Star; // Star makes it crash as well
//return new GridLength(numberValue); // This works fine
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is GridLength gridLength))
{
throw new Exception($"Type {value.GetType().FullName} is not GridLenght");
}
return gridLength.Value;
}
}
XAML
<ContentPage.Resources>
<ResourceDictionary>
<conv:NumberToGridLengthConverter x:Key="numberToGridLengthConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Grid Grid.Column="1" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=MovementCalm, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
<ColumnDefinition Width="{Binding Path=MovementRapid, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
</Grid.ColumnDefinitions>
<BoxView Grid.Column="0" BackgroundColor="LightGreen" HorizontalOptions="FillAndExpand" HeightRequest="20" />
<BoxView Grid.Column="1" BackgroundColor="Orange" HorizontalOptions="FillAndExpand" HeightRequest="20" />
</Grid>
</StackLayout>
</ContentPage.Content>
ViewModel
public class StatisticsViewModel : BaseViewModel
{
private double _movementCalm;
public double MovementCalm
{
get => _movementCalm;
set => SetProperty(ref _movementCalm, value);
}
private double _movementRapid;
public double MovementRapid
{
get => _movementRapid;
set => SetProperty(ref _movementRapid, value);
}
public StatisticsViewModel()
{
}
public override void OnAppearing()
{
base.OnAppearing();
SetMovement();
}
private void SetMovement()
{
MovementCalm = 90f;
MovementRapid = 10f;
}
}
public abstract class BaseViewModel : INotifyPropertyChanged
{
public virtual void OnAppearing()
{
}
public virtual void OnBindingContextChanged()
{
}
public virtual void OnDisappearing()
{
}
#region 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 = "")
{
var changed = PropertyChanged;
if (changed == null)
{
return;
}
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
知道如何让它与 Star 单位一起使用吗?
首先,如果将GridUnitType
设置为Star
,Column
的宽度将永远不会改变(每个Column
将占据屏幕的1/2如果你有 2 Columns
).
//
// Summary:
// Interpret the Xamarin.Forms.GridLength.Value property value as a proportional
// weight, to be laid out after rows and columns with Xamarin.Forms.GridUnitType.Absolute
// or Xamarin.Forms.GridUnitType.Auto are accounted for.
//
// Remarks:
// After all the rows and columns of type Xamarin.Forms.GridUnitType.Absolute and
// Xamarin.Forms.GridUnitType.Auto are laid out, each of the corresponding remaining
// rows or columns, which are of type Xamarin.Forms.GridUnitType.Star, receive a
// fraction of the remaining available space. This fraction is determined by dividing
// each row's or column's Xamarin.Forms.GridLength.Value property value by the sum
// of all the row or column Xamarin.Forms.GridLength.Value property values, correspondingly,
// including its own.
Star = 1,
另外,当你设置Binding Path
时,你必须同时设置BindingContext
。
例如,我将宽度的值绑定到滑块。
<ContentPage.Content>
<StackLayout>
<Slider x:Name="slider" Maximum="200" Minimum="100" Value="100" />
<Grid Grid.Column="1" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition BindingContext="{x:Reference slider}" Width="{Binding Path=Value, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
<ColumnDefinition BindingContext="{x:Reference slider}" Width="{Binding Path=Value, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
</Grid.ColumnDefinitions>
<BoxView Grid.Column="0" BackgroundColor="LightGreen" HorizontalOptions="FillAndExpand" HeightRequest="20" />
<BoxView Grid.Column="1" BackgroundColor="Orange" HorizontalOptions="FillAndExpand" HeightRequest="20" />
</Grid>
</StackLayout>
</ContentPage.Content>
将 GridUnitType
设置为 Star
不会导致崩溃。因此,如果您的问题仍然出现,您可以创建一个包含该问题的示例,以便我可以在我这边进行测试。
更新:
我发现了你的问题!
您应该在构造函数中初始化 MovementCalm 和 MovementRapid。
public StatisticsViewModel()
{
SetMovement();
}
在您的内容页面(例如 MainPage)
public MainPage()
{
InitializeComponent();
BindingContext = new StatisticsViewModel();
}
方法 OnAppearing 和 OnDisappearing 永远不会被调用,因为 ViewModel 不是 ContentPage.
所以宽度的值总是0。当设置GridUnitType为Star时它会崩溃。但是当你将它设置为 Absolute 它不会因为 Absolute 允许值为 0 .
我在尝试将双精度转换为星型单位的 GridLength 时出错。转换后的本身工作正常,但我在运行时遇到错误
"System.ArgumentException: NaN is not a valid value for width\n at Xamarin.Forms.Size..ctor (System.Double width, System.Double height) [0x00008] in D:\a\s\Xamarin.Forms.Core\Size.cs:19 \n at Xamarin.Forms.Grid.ContractColumnsIfNeeded (System.Double width, System.Func`2[T,TResult] predicate) [0x00075] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:213 \n at Xamarin.Forms.Grid.MeasureAndContractStarredColumns (System.Double width, System.Double height, System.Double totalStarsWidth) [0x000bb] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:397 \n at Xamarin.Forms.Grid.MeasureGrid (System.Double width, System.Double height, System.Boolean requestSize) [0x0010e] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:509 \n at Xamarin.Forms.Grid.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0002a] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:58 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\ \s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.Grid.MeasureStarredRows () [0x000c3] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:548 \n at Xamarin.Forms.Grid.MeasureAndContractStarredRows (System.Double width, System.Double height, System.Double totalStarsHeight) [0x00000] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:403 \n at Xamarin.Forms.Grid.MeasureGrid (System.Double width, System.Double height, System.Boolean requestSize) [0x0011 7] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:510 \n at Xamarin.Forms.Grid.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0002a] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:58 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.StackLayout.CalculateNaiveLayout (Xamarin.Forms.Stac kLayout+LayoutInformation layout, Xamarin.Forms.StackOrientation orientation, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint) [0x000a8] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:163 \n at Xamarin.Forms.StackLayout.CalculateLayout (Xamarin.Forms.StackLayout+LayoutInformation layout, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint, System.Boolean processExpanders) [0x00058] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:123 \n at Xamarin.Forms.StackLayout.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00019] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:80 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\ s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.Grid.CalculateAutoCells (System.Double width, System.Double height) [0x000e5] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:131 \n at Xamarin.Forms.Grid.MeasureGrid (System.Double width, System.Double height, System.Boolean requestSize) [0x0000c] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:483 \n at Xamarin.Forms.Grid.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0002a] in D:\a\s\Xamarin.Forms.Core\GridCalc.cs:58 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.ScrollView.OnSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x0005d] in D:\a\s\Xamarin.Forms.Core\ScrollView.cs:233 \n at Xamarin.Forms.VisualElement.OnMeasure (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:641 \n at Xamarin.Forms.VisualElement.GetSizeRequest (System.Dou ble widthConstraint, System.Double heightConstraint) [0x00053] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:523 \n at Xamarin.Forms.Layout.GetSizeRequest (System.Double widthConstraint, System.Double heightConstraint) [0x00000] in D:\a\s\Xamarin.Forms.Core\Layout.cs:131 \n at Xamarin.Forms.VisualElement.Measure (System.Double widthConstraint, System.Double heightConstraint, Xamarin.Forms.MeasureFlags flags) [0x00054] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:581 \n at Xamarin.Forms.StackLayout.CalculateNaiveLayout (Xamarin.Forms.StackLayout+LayoutInformation layout, Xamarin.Forms.StackOrientation orientation, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint) [0x000a8] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:163 \n at Xamarin.Forms.StackLayout.CalculateLayout (Xamarin.Forms.StackLayout+LayoutInformation layout, System.Double x, System.Double y, System.Double widthConstraint, System.Double heightConstraint, System.Boolean pro cessExpanders) [0x00058] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:123 \n at Xamarin.Forms.StackLayout.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0005b] in D:\a\s\Xamarin.Forms.Core\StackLayout.cs:57 \n at Xamarin.Forms.Layout.UpdateChildrenLayout () [0x0014b] in D:\a\s\Xamarin.Forms.Core\Layout.cs:263 \n at Xamarin.Forms.Layout.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:223 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.L ayout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x001da] in D:\a\s\Xamarin.Forms.Core\Layout.cs:177 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0010d] in D:\a\s\Xamarin.Forms.Core\Page.cs:187 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualEleme nt.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x0005f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:146 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0010d] in D:\a\s\Xamarin.Forms.Core\Page.cs:187 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\ 1\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x0005f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:146 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x0010d] in D:\a\s\Xamarin.Forms.Core\Page.cs:187 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, Sy stem.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region) [0x0005f] in D:\a\s\Xamarin.Forms.Core\Layout.cs:146 \n at Xamarin.Forms.Page.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x00103] in D:\a\s\Xamarin.Forms.C ore\Page.cs:185 \n at Xamarin.Forms.Page.UpdateChildrenLayout () [0x000c6] in D:\a\s\Xamarin.Forms.Core\Page.cs:259 \n at Xamarin.Forms.Page.OnSizeAllocated (System.Double width, System.Double height) [0x0000f] in D:\a\s\Xamarin.Forms.Core\Page.cs:240 \n at Xamarin.Forms.VisualElement.SizeAllocated (System.Double width, System.Double height) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:679 \n at Xamarin.Forms.VisualElement.SetSize (System.Double width, System.Double height) [0x00021] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:908 \n at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) [0x0005d] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:186 \n at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) [0x00000] in D:\a\s\Xamarin.Forms.Core\VisualElement.cs:565 \n at Xamarin.Forms.Platform.iOS.NavigationRenderer.ViewDidLayoutSubviews () [0x00172] in D:\a\s\Xamarin.Forms.Platform.iOS\Renderers\NavigationRe nderer.cs:182 \n at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)\n at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.4.0.64/src/Xamarin.iOS/UIKit/UIApplication.cs:79 \n at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0002c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.4.0.64/src/Xamarin.iOS/UIKit/UIApplication.cs:63 \n at PrenCare.iOS.Application.Main (System.String[] args) [0x00002] in C:\Users\ondre\source\repos\PrenCare\src\Version02\PrenCare\PrenCare.iOS\Main.cs:19 "
。奇怪的是,当我使用绝对单位时,转换器工作得很好。
转换器
public class NumberToGridLengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is double numberValue))
{
throw new Exception($"Type {value.GetType().FullName} cannot be converted to GridLenght");
}
return new GridLength(numberValue, GridUnitType.Star); // Star makes it crash
//return GridLength.Star; // Star makes it crash as well
//return new GridLength(numberValue); // This works fine
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is GridLength gridLength))
{
throw new Exception($"Type {value.GetType().FullName} is not GridLenght");
}
return gridLength.Value;
}
}
XAML
<ContentPage.Resources>
<ResourceDictionary>
<conv:NumberToGridLengthConverter x:Key="numberToGridLengthConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Grid Grid.Column="1" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=MovementCalm, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
<ColumnDefinition Width="{Binding Path=MovementRapid, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
</Grid.ColumnDefinitions>
<BoxView Grid.Column="0" BackgroundColor="LightGreen" HorizontalOptions="FillAndExpand" HeightRequest="20" />
<BoxView Grid.Column="1" BackgroundColor="Orange" HorizontalOptions="FillAndExpand" HeightRequest="20" />
</Grid>
</StackLayout>
</ContentPage.Content>
ViewModel
public class StatisticsViewModel : BaseViewModel
{
private double _movementCalm;
public double MovementCalm
{
get => _movementCalm;
set => SetProperty(ref _movementCalm, value);
}
private double _movementRapid;
public double MovementRapid
{
get => _movementRapid;
set => SetProperty(ref _movementRapid, value);
}
public StatisticsViewModel()
{
}
public override void OnAppearing()
{
base.OnAppearing();
SetMovement();
}
private void SetMovement()
{
MovementCalm = 90f;
MovementRapid = 10f;
}
}
public abstract class BaseViewModel : INotifyPropertyChanged
{
public virtual void OnAppearing()
{
}
public virtual void OnBindingContextChanged()
{
}
public virtual void OnDisappearing()
{
}
#region 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 = "")
{
var changed = PropertyChanged;
if (changed == null)
{
return;
}
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
知道如何让它与 Star 单位一起使用吗?
首先,如果将GridUnitType
设置为Star
,Column
的宽度将永远不会改变(每个Column
将占据屏幕的1/2如果你有 2 Columns
).
//
// Summary:
// Interpret the Xamarin.Forms.GridLength.Value property value as a proportional
// weight, to be laid out after rows and columns with Xamarin.Forms.GridUnitType.Absolute
// or Xamarin.Forms.GridUnitType.Auto are accounted for.
//
// Remarks:
// After all the rows and columns of type Xamarin.Forms.GridUnitType.Absolute and
// Xamarin.Forms.GridUnitType.Auto are laid out, each of the corresponding remaining
// rows or columns, which are of type Xamarin.Forms.GridUnitType.Star, receive a
// fraction of the remaining available space. This fraction is determined by dividing
// each row's or column's Xamarin.Forms.GridLength.Value property value by the sum
// of all the row or column Xamarin.Forms.GridLength.Value property values, correspondingly,
// including its own.
Star = 1,
另外,当你设置Binding Path
时,你必须同时设置BindingContext
。
例如,我将宽度的值绑定到滑块。
<ContentPage.Content>
<StackLayout>
<Slider x:Name="slider" Maximum="200" Minimum="100" Value="100" />
<Grid Grid.Column="1" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition BindingContext="{x:Reference slider}" Width="{Binding Path=Value, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
<ColumnDefinition BindingContext="{x:Reference slider}" Width="{Binding Path=Value, Mode=TwoWay, Converter={StaticResource numberToGridLengthConverter}}" />
</Grid.ColumnDefinitions>
<BoxView Grid.Column="0" BackgroundColor="LightGreen" HorizontalOptions="FillAndExpand" HeightRequest="20" />
<BoxView Grid.Column="1" BackgroundColor="Orange" HorizontalOptions="FillAndExpand" HeightRequest="20" />
</Grid>
</StackLayout>
</ContentPage.Content>
将 GridUnitType
设置为 Star
不会导致崩溃。因此,如果您的问题仍然出现,您可以创建一个包含该问题的示例,以便我可以在我这边进行测试。
更新:
我发现了你的问题!
您应该在构造函数中初始化 MovementCalm 和 MovementRapid。
public StatisticsViewModel()
{
SetMovement();
}
在您的内容页面(例如 MainPage)
public MainPage()
{
InitializeComponent();
BindingContext = new StatisticsViewModel();
}
方法 OnAppearing 和 OnDisappearing 永远不会被调用,因为 ViewModel 不是 ContentPage.
所以宽度的值总是0。当设置GridUnitType为Star时它会崩溃。但是当你将它设置为 Absolute 它不会因为 Absolute 允许值为 0 .