gpt4 book ai didi

c# - Xamarin slider : 'Value is an invalid value for Maximum' (Only when navigating away from a page)

转载 作者:行者123 更新时间:2023-12-05 02:05:04 27 4
gpt4 key购买 nike

我需要在 CollectionView 中为每个项目显示不同的 UI 元素. CollectionView 中每一项的基本类型是 Setting .有不同类型的设置:AnalogSetting , BooleanSetting , RangeSetting等。每个派生类都有一组不同的 UI 元素,以允许用户与之交互。 BooleanSetting可能有一个简单的拨动开关,而 AnalogSetting有一个 slider 。设置的数量和类型在运行时交付,并且可以即时更改。

我能做到的最简单的方法是使用 DataTemplateSelector然后定义不同的DataTemplates对于每个派生 Setting类(class)。有一个特别的 DataTemplate这会导致我的应用程序在我离开显示 CollectionView 的页面时崩溃.

我有以下 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>

SliderBehavior DataTemplate 中使用的类:

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

几件事:

  1. OnDetachingFrom在我的习惯中Behavior<Slider>类永远不会被调用,即使在 OnDisappearing 之后也是如此调用拥有页面的功能
  2. 我知道在最小值之前设置 slider 最大值的要求。 Slider 很可能很奇怪类在这里咬我。
  3. 我相信AnalogSetting当页面离开时,模型被销毁,但是 Behavior<Slider>类仍在尝试使用它最初绑定(bind)的值。我不知道这 100%,但这是我目前的猜测。

调试这个很痛苦,因为我的代码都不在调用堆栈中。任何有关如何在调用堆栈中找出更多信息的提示都将不胜感激。

我愿意接受关于使用 DataTemplateSelector 以外的东西的建议和 Behaviors得到我想要的东西。

最佳答案

当我们使用 DataTemplate 时,我们的 slider 也遇到了问题,我们所做的如下:由于每个 DataTemplate 实际上只是一个美化的 XAML 元素,我们可以安全地设置一个 x:Name 我们 slider 上的属性,它将是唯一的,并且不会在运行时/编译期间引起任何关于非唯一名称的冲突。

所以在我们的 SliderTemplate.xaml 中我们设置了最大值和最小值

    <Slider 
x:Name="NoteSlider"
Maximum="5"
Minimum="0"
...
/>

然后在我们的 SliderTemplate.xaml.cs 中:

  1. 定义我们正在使用的 View 模型

  2. 重写 OnBindingContextChanged 以实际实例化它

  3. 设置正确的最小/最大值。

    私有(private) 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 可能会被处理掉,但 View 仍然处于事件状态,因此它处于不良状态。这就是我们解决该问题的方式

关于c# - Xamarin slider : 'Value is an invalid value for Maximum' (Only when navigating away from a page),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63855146/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com