簡體   English   中英

Xamarin 滑塊:“值是最大值的無效值”(僅當導航離開頁面時)

[英]Xamarin Slider: 'Value is an invalid value for Maximum' (Only when navigating away from a page)

我需要在CollectionView中為每個項目顯示不同的 UI 元素。 CollectionView中每個項目的基本類型是一個Setting 有不同類型的設置: AnalogSettingBooleanSettingRangeSetting等。每個派生類都有一組不同的 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 

一些事情:

  1. 我的自定義Behavior<Slider>類中的OnDetachingFrom永遠不會被調用,即使在調用擁有頁面的OnDisappearing函數之后
  2. 我知道在最小值之前設置滑塊最大值的要求。 Slider類的奇怪之處很可能在這里咬我。
  3. 我相信當頁面被導航離開時, AnalogSetting模型正在被破壞,但Behavior<Slider>類仍在嘗試使用它最初綁定的值。 我不知道 100%,但這是我目前的猜測。

調試這很痛苦,因為我的代碼都沒有在調用堆棧中。 任何有關如何在調用堆棧中找出更多信息的提示將不勝感激。

我願意接受關於使用DataTemplateSelectorBehaviors以外的東西來獲得我想要的東西的建議。

當我們使用 DataTemplate 時,我們的滑塊也遇到了問題,我們所做的如下:由於每個 DataTemplate 實際上只是一個美化的 XAML 元素,我們可以安全地在滑塊上​​設置x:Name屬性,它將是唯一並且不會在運行時/編譯期間導致任何關於非唯一名稱的沖突。

所以在我們的 SliderTemplate.xaml 中,我們設置了一個最大值和最小值

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

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

  1. 定義我們正在使用的視圖模型

  2. 覆蓋 OnBindingContextChanged 以實際實例化它

  3. 設置正確的最小/最大值。

    私有 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM