[英]Xamarin Slider: 'Value is an invalid value for Maximum' (Only when navigating away from a page)
I have a need to display different UI elements per item in a CollectionView
.我需要在
CollectionView
中为每个项目显示不同的 UI 元素。 The base type of each item in the CollectionView
is a Setting
. CollectionView
中每个项目的基本类型是一个Setting
。 There are different types of settings: AnalogSetting
, BooleanSetting
, RangeSetting
, etc. Each derived class has a different set of UI elements to allow the user to interact with it.有不同类型的设置:
AnalogSetting
、 BooleanSetting
、 RangeSetting
等。每个派生类都有一组不同的 UI 元素以允许用户与其交互。 BooleanSetting
may have a simple toggle switch while the AnalogSetting
has a slider. BooleanSetting
可能有一个简单的切换开关,而AnalogSetting
有一个滑块。 The amount and types of settings are delivered at runtime and can change on the fly.设置的数量和类型在运行时提供,并且可以即时更改。
The simplest way I could manage this was to use a DataTemplateSelector
and then define different DataTemplates
for each derived Setting
class.我可以管理的最简单的方法是使用
DataTemplateSelector
,然后为每个派生的Setting
类定义不同的DataTemplates
。 There is a particular DataTemplate
that causes my app to crash whenever I navigate away from the page that is displaying the CollectionView
.当我离开显示
CollectionView
的页面时,有一个特定的DataTemplate
会导致我的应用程序崩溃。
I have the following CollectionView
:我有以下
CollectionView
:
...
<CollectionView
x:Name="SettingListView"
ItemsSource="{Binding Settings}"
ItemTemplate="{StaticResource settingSelector}"
SelectionMode="None">
</CollectionView>
The particular DataTemplate
that is causing me grief:引起我悲伤的特定
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>
The SliderBehavior
class being used in the 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;
}
}
} }
The error given to me whenever I navigate away from the page that is displaying this DataTemplate
:每当我离开显示此
DataTemplate
的页面时,给我的错误:
System.ArgumentException: 'Value is an invalid value for Maximum
Parameter name: value'
The relevant portion of the callstack given to me when this exception is thrown:抛出此异常时提供给我的调用堆栈的相关部分:
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
A couple things:一些事情:
OnDetachingFrom
in my custom Behavior<Slider>
class never gets called, even after the OnDisappearing
function of the owning page is invokedBehavior<Slider>
类中的OnDetachingFrom
永远不会被调用,即使在调用拥有页面的OnDisappearing
函数之后Slider
class is biting me here. Slider
类的奇怪之处很可能在这里咬我。AnalogSetting
model is being destroyed when the page is navigated away from, but the Behavior<Slider>
class is still attempting to use the values that it bound to initially.AnalogSetting
模型正在被破坏,但Behavior<Slider>
类仍在尝试使用它最初绑定的值。 I don't know this 100%, but it's my current guess. Debugging this has been a pain, since none of my code is in the callstack.调试这很痛苦,因为我的代码都没有在调用堆栈中。 Any tips on how to go about figuring out more information within the callstack would be appreciated.
任何有关如何在调用堆栈中找出更多信息的提示将不胜感激。
I'm open to suggestions in regards to using something other than DataTemplateSelector
and Behaviors
to get what I'm after.我愿意接受关于使用
DataTemplateSelector
和Behaviors
以外的东西来获得我想要的东西的建议。
We too had an issue with our sliders when it came to us using a DataTemplate, what we did is as follows: Since each DataTemplate is really just a glorified XAML element we can safely set a x:Name
property on our slider and it will be unique and won't cause any conflicts during runttime/compile about non unique names.当我们使用 DataTemplate 时,我们的滑块也遇到了问题,我们所做的如下:由于每个 DataTemplate 实际上只是一个美化的 XAML 元素,我们可以安全地在滑块上设置
x:Name
属性,它将是唯一并且不会在运行时/编译期间导致任何关于非唯一名称的冲突。
So In our SliderTemplate.xaml we set a Max and Min所以在我们的 SliderTemplate.xaml 中,我们设置了一个最大值和最小值
<Slider
x:Name="NoteSlider"
Maximum="5"
Minimum="0"
...
/>
Then in our SliderTemplate.xaml.cs:然后在我们的 SliderTemplate.xaml.cs 中:
Define our view model we are using定义我们正在使用的视图模型
Override OnBindingContextChanged to actually instantiate it覆盖 OnBindingContextChanged 以实际实例化它
Set the correct min/max values.设置正确的最小/最大值。
private MyViewModel controlModel;私有 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; } ... } }
I want to say the reason it throws that exception is because odds are the VM is disposed when you are navigating away, but the view is still sorta alive and thus it gets in a bad state.我想说它抛出该异常的原因是因为当您导航离开时,VM 可能已被处理,但视图仍然处于活动状态,因此它处于不良状态。 That is how we solved that issue
我们就是这样解决这个问题的
I was receiving the same error when leaving the page.离开页面时我收到了同样的错误。 To fix it I added the
FallbackValue
parameter to the Maximum
attribute in the XAML, and set it to a number greater than what any of my minimum numbers would possibly be.为了修复它,我将
FallbackValue
参数添加到 XAML 中的Maximum
属性,并将其设置为大于我的任何最小数字可能的数字。
<Slider Maximum="{Binding Max, FallbackValue=1000000}" Minimum="{Binding Min}" Value="{Binding SettingValue}"></Slider>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.