我的可绑定属性不会将更改转发到XAML中的绑定集

n1bvdmb6  于 2023-08-01  发布在  其他
关注(0)|答案(1)|浏览(88)

我创建了一个DoubleIntSlider自定义视图,其中包含2个滑块,每个Slider.Value对应一个BindableProperties。但是我无法让BindableProperties更新父页面分配给它的属性。虽然使用常规的Slider而不是我的自定义视图,但具有完全相同的设置可以正常工作。
我的FilterPage页面是这样定义的:

public partial class FilterPage : ContentPage
{
    public RestaurantFilter Filter { get; }
    
    public FilterPage(RestaurantFilter filter)
    {
        Filter = filter;
        InitializeComponent();
    }
}

public class RestaurantFilter : INotifyPropertyChanged
{
    private int _minQuality = Restaurant.MIN_QUALITY;

    public int MinQuality
    {
        get => _minQuality;
        set => SetField(ref _minQuality, value);
    }

    private int _minPrice = Restaurant.MIN_PRICE;
    public int MinPrice 
    {
        get => _minPrice;
        set => SetField(ref _minPrice, value);
    }

    private int _maxPrice = Restaurant.MAX_PRICE;
    public int MaxPrice 
    {
        get => _maxPrice;
        set => SetField(ref _maxPrice, value);
    }

    // ...
}

字符串
在这个页面的XAML中,我有两个视图:Slider和自定义DoubleIntSlider视图,定义如下:

<Label 
    Text="Min Quality"
    HorizontalOptions="FillAndExpand" />
<views:IntegerSlider Value="{Binding .Filter.MinQuality}" Maximum="10" Minimum="1" />

<Label 
    Text="Price"
    HorizontalOptions="FillAndExpand" />
<views:DoubleIntSlider 
    MinValue="{Binding .Filter.MinPrice}" 
    MaxValue="{Binding .Filter.MaxPrice}" 
    Maximum="10" Minimum="1" />


绑定上下文是页面的示例。当触摸页面中的Sliders时,只有RestaurantFilter.MinQuality属性的setter被调用。
DoubleIntSliderMinValueMaxValue属性的定义如下:

public partial class DoubleIntSlider : StackLayout
{
    
    public static readonly BindableProperty MinValueProperty = BindableProperty.Create(
        nameof(MinValue),
        typeof(int),
        typeof(DoubleIntSlider),
        0,
        BindingMode.TwoWay,
        coerceValue: CoerceMinValue, 
        propertyChanged: MinChanged);

    public int MinValue
    {
        get => (int)GetValue(MinValueProperty);
        set => SetValue(MinValueProperty, value);
    }

    public static readonly BindableProperty MaxValueProperty = BindableProperty.Create(
        nameof(MaxValue),
        typeof(int),
        typeof(DoubleIntSlider),
        10,
        BindingMode.TwoWay,
        coerceValue: CoerceMaxValue, 
        propertyChanged: MaxChanged);   

    public int MaxValue
    {
        get => (int)GetValue(MaxValueProperty);
        set => SetValue(MaxValueProperty, value);
    }
    
    private static object CoerceMinValue(BindableObject bindable, object value)
    {
        var instance = (DoubleIntSlider)bindable;
        int minValue = (int)value;

        return minValue.Clamp(instance.Minimum, instance.MaxValue);
    }
    
    private static object CoerceMaxValue(BindableObject bindable, object value)
    {
        var instance = (DoubleIntSlider)bindable;
        int maxValue = (int)value;

        return maxValue.Clamp(instance.MinValue, instance.Maximum);
    }
    
    private static void MinChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var ctrl = (DoubleIntSlider)bindable;
        ctrl.MinValue = (int)newValue;
    }
    
    private static void MaxChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var ctrl = (DoubleIntSlider)bindable;
        ctrl.MaxValue = (int)newValue;
    }

    // ...
}


DoubleIntSlider视图有,你猜对了,2个滑块如下所示:

<Slider
        Value="{Binding .MinValue}"
        Maximum="{Binding .Maximum}"
        Minimum="{Binding .Minimum}"
        HorizontalOptions="FillAndExpand"
        />
    
    <Slider
        Value="{Binding .MaxValue}"
        Maximum="{Binding .Maximum}"
        Minimum="{Binding .Minimum}"
        HorizontalOptions="FillAndExpand"
    />


我为BindableProperty对象尝试了所有可能的BindingMode。我还尝试了使用和不使用propertyChanged委托。我还尝试将强制代码直接放入DoubleIntSlider属性设置器中。
但是我无法在更新滑块时调用RestaurantFilter.MinPriceRestaurantFilter.MaxPrice的setter。

编辑:

下面是DoubleIntSlider的构造函数:

public DoubleIntSlider()
{
    PropertyChanged += (_, __) =>
    {
        UpdateBar(); // This method only reads the values
    };
    
    
    InitializeComponent();
}


DoubleIntSlider的完整XAML:

<?xml version="1.0" encoding="utf-8"?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:App1.Views;assembly=App1"
             x:Class="App1.Views.DoubleIntSlider"
             x:Name="this"
             BindingContext="{x:Reference this}"
             Padding="10">

    <Slider
        Value="{Binding .MinValue}"
        Maximum="{Binding .Maximum}"
        Minimum="{Binding .Minimum}"
        HorizontalOptions="FillAndExpand"
        />
    
    <StackLayout Orientation="Horizontal"
                 HeightRequest="50"
                 Spacing="0"
                 Padding="10"
                 x:Name="BarLayout">
        <Rectangle x:Name="BarLeftMargin"
                   Stroke="Gray"
                   StrokeThickness="4"
                   StrokeDashArray="1,1"
                   StrokeDashOffset="6"
                   HeightRequest="5"
                   HorizontalOptions="Center"
                   VerticalOptions="Center" />
        <Rectangle Fill="Blue"
                   HorizontalOptions="FillAndExpand"
                   VerticalOptions="FillAndExpand" />
        <Rectangle x:Name="BarRightMargin"
                   Stroke="Gray"
                   StrokeThickness="4"
                   StrokeDashArray="1,1"
                   StrokeDashOffset="6"
                   HorizontalOptions="Center"
                   HeightRequest="5"
                   VerticalOptions="Center" />
    </StackLayout>
    
    <Slider
        Value="{Binding .MaxValue}"
        Maximum="{Binding .Maximum}"
        Minimum="{Binding .Minimum}"
        HorizontalOptions="FillAndExpand"
    />
</StackLayout>

pzfprimi

pzfprimi1#

根据ToolmakerSteve的说法,您可以删除BindingContext="{x:Reference this}"来修复它。
有关更多信息,您可以参考前面的答案:.Net MAUI data binding not carrying through to custom component的数据。

相关问题