[英]Xamarin Slider: 'Value is an invalid value for Maximum' (Only when navigating away from a page)
我需要在CollectionView
中為每個項目顯示不同的 UI 元素。 CollectionView
中每個項目的基本類型是一個Setting
。 有不同類型的設置: AnalogSetting
、 BooleanSetting
、 RangeSetting
等。每個派生類都有一組不同的 UI 元素以允許用戶與其交互。 BooleanSetting
可能有一個簡單的切換開關,而AnalogSetting
有一個滑塊。 設置的數量和類型在運行時提供,並且可以即時更改。
我可以管理的最簡單的方法是使用DataTemplateSelector
,然后為每個派生的Setting
類定義不同的DataTemplates
。 當我離開顯示CollectionView
的頁面時,有一個特定的DataTemplate
會導致我的應用程序崩潰。
我有以下CollectionView
:
...
<CollectionView
x:Name="SettingListView"
ItemsSource="{Binding Settings}"
ItemTemplate="{StaticResource settingSelector}"
SelectionMode="None">
</CollectionView>
引起我悲傷的特定DataTemplate
:
<DataTemplate x:Key="AnalogSetting">
<StackLayout x:DataType="model:AnalogSetting">
<Label Text="{Binding Name}"/>
<Slider Maximum="{Binding MaximumValue}" Minimum="{Binding MinimumValue}" Value="{Binding AnalogValue}">
<Slider.Behaviors>
<behaviors:SliderBehavior Command="{Binding SetValue}" />
</Slider.Behaviors>
</Slider>
</StackLayout>
</DataTemplate>
在DataTemplate
中使用的SliderBehavior
類:
public class SliderBehavior : Behavior<Slider>
{
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(SliderBehavior), null);
public Slider Bindable { get; private set; }
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
protected override void OnAttachedTo(Slider bindable)
{
base.OnAttachedTo(bindable);
Bindable = bindable;
Bindable.BindingContextChanged += OnBindingContextChanged;
Bindable.ValueChanged += OnValueChanged;
}
protected override void OnDetachingFrom(Slider bindable)
{
base.OnDetachingFrom(bindable);
Bindable.BindingContextChanged -= OnBindingContextChanged;
Bindable.ValueChanged -= OnValueChanged;
Bindable = null;
}
private void OnBindingContextChanged(object sender, EventArgs e)
{
OnBindingContextChanged();
BindingContext = Bindable.BindingContext;
}
private void OnValueChanged(object sender, ValueChangedEventArgs e)
{
double value = Math.Round(e.NewValue);
if (value != Math.Round(e.OldValue))
{
Command?.Execute(value.ToString());
}
Bindable.Value = value;
}
}
}
每當我離開顯示此DataTemplate
的頁面時,給我的錯誤:
System.ArgumentException: 'Value is an invalid value for Maximum
Parameter name: value'
拋出此異常時提供給我的調用堆棧的相關部分:
0xFFFFFFFFFFFFFFFF in System.Diagnostics.Debugger.Mono_UnhandledException_internal
0x1 in System.Diagnostics.Debugger.Mono_UnhandledException at /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.Diagnostics/Debugger.cs:125,4
0x26 in Android.Runtime.DynamicMethodNameCounter.148
0xBA in Xamarin.Forms.BindableObject.SetValueCore at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:368,5
0x121 in Xamarin.Forms.Internals.TypedBinding<Common.Models.AnalogSetting,double>.ApplyCore at D:\a\1\s\Xamarin.Forms.Core\TypedBinding.cs:218,5
0x5D in Xamarin.Forms.Internals.TypedBinding<Common.Models.AnalogSetting,double>.Apply at D:\a\1\s\Xamarin.Forms.Core\TypedBinding.cs:135,4
0x51 in Xamarin.Forms.BindableObject.ApplyBindings at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:480,5
0x5D in Xamarin.Forms.BindableObject.SetInheritedBindingContext at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:209,4
0x2 in Xamarin.Forms.Element.SetChildInheritedBindingContext at D:\a\1\s\Xamarin.Forms.Core\Element.cs:470,4
0x8 in Xamarin.Forms.Element.<OnBindingContextChanged>b__82_0 at D:\a\1\s\Xamarin.Forms.Core\Element.cs:308,5
0x2F in Xamarin.Forms.BindableObjectExtensions.PropagateBindingContext<Xamarin.Forms.Element> at D:\a\1\s\Xamarin.Forms.Core\BindableObjectExtensions.cs:28,5
0x13 in Xamarin.Forms.Element.OnBindingContextChanged at D:\a\1\s\Xamarin.Forms.Core\Element.cs:306,4
0x7 in Xamarin.Forms.VisualElement.OnBindingContextChanged at D:\a\1\s\Xamarin.Forms.Core\VisualElement.cs:812,4
0xD in Xamarin.Forms.View.OnBindingContextChanged at D:\a\1\s\Xamarin.Forms.Core\View.cs:158,4
0x10 in Xamarin.Forms.BindableObject.BindingContextPropertyChanged at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:500,4 C#
0x12E in Xamarin.Forms.BindableObject.SetValueActual at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:463,5
0x17C in Xamarin.Forms.BindableObject.SetValueCore at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:397,5
0x56 in Xamarin.Forms.BindableObject.SetValue at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:334,4
0x5 in Xamarin.Forms.BindableObject.SetValue at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:311,68
0x7 in Xamarin.Forms.BindableObject.set_BindingContext at D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:41,11
0x13 in Xamarin.Forms.Platform.Android.TemplatedItemViewHolder.Recycle at D:\a\1\s\Xamarin.Forms.Platform.Android\CollectionView\TemplatedItemViewHolder.cs:38,4
0x16 in Xamarin.Forms.Platform.Android.ItemsViewAdapter<Xamarin.Forms.GroupableItemsView,Xamarin.Forms.Platform.Android.IGroupableItemsViewSource>.OnViewRecycled at D:\a\1\s\Xamarin.Forms.Platform.Android\CollectionView\ItemsViewAdapter.cs:64,5
0x32 in Xamarin.Forms.Platform.Android.SelectableItemsViewAdapter<Xamarin.Forms.GroupableItemsView,Xamarin.Forms.Platform.Android.IGroupableItemsViewSource>.OnViewRecycled at D:\a\1\s\Xamarin.Forms.Platform.Android\CollectionView\SelectableItemsViewAdapter.cs:53,4
0x11 in
一些事情:
Behavior<Slider>
類中的OnDetachingFrom
永遠不會被調用,即使在調用擁有頁面的OnDisappearing
函數之后Slider
類的奇怪之處很可能在這里咬我。AnalogSetting
模型正在被破壞,但Behavior<Slider>
類仍在嘗試使用它最初綁定的值。 我不知道 100%,但這是我目前的猜測。調試這很痛苦,因為我的代碼都沒有在調用堆棧中。 任何有關如何在調用堆棧中找出更多信息的提示將不勝感激。
我願意接受關於使用DataTemplateSelector
和Behaviors
以外的東西來獲得我想要的東西的建議。
當我們使用 DataTemplate 時,我們的滑塊也遇到了問題,我們所做的如下:由於每個 DataTemplate 實際上只是一個美化的 XAML 元素,我們可以安全地在滑塊上設置x:Name
屬性,它將是唯一並且不會在運行時/編譯期間導致任何關於非唯一名稱的沖突。
所以在我們的 SliderTemplate.xaml 中,我們設置了一個最大值和最小值
<Slider
x:Name="NoteSlider"
Maximum="5"
Minimum="0"
...
/>
然后在我們的 SliderTemplate.xaml.cs 中:
定義我們正在使用的視圖模型
覆蓋 OnBindingContextChanged 以實際實例化它
設置正確的最小/最大值。
私有 MyViewModel 控制模型;
public SliderInputTemplate() { InitializeComponent(); } protected override void OnBindingContextChanged() { base.OnBindingContextChanged(); controlModel = this.BindingContext as MyViewModel ; BindingContext = controlModel; } protected override void OnAppearing() { base.OnAppearing(); if(controlModel != null) { //controlModel.UpdateSlider(); if(controlModel.Max > controlModel.Min) { NoteSlider.Maximum = controlModel.Max; NoteSlider.Minimum = controlModel.Min; NoteSlider.Value = controlModel.SliderValue; } ... } }
我想說它拋出該異常的原因是因為當您導航離開時,VM 可能已被處理,但視圖仍然處於活動狀態,因此它處於不良狀態。 我們就是這樣解決這個問題的
離開頁面時我收到了同樣的錯誤。 為了修復它,我將FallbackValue
參數添加到 XAML 中的Maximum
屬性,並將其設置為大於我的任何最小數字可能的數字。
<Slider Maximum="{Binding Max, FallbackValue=1000000}" Minimum="{Binding Min}" Value="{Binding SettingValue}"></Slider>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.