我创建了一个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被调用。DoubleIntSlider
MinValue
和MaxValue
属性的定义如下:
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.MinPrice
和RestaurantFilter.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>
型
1条答案
按热度按时间pzfprimi1#
根据ToolmakerSteve的说法,您可以删除
BindingContext="{x:Reference this}"
来修复它。有关更多信息,您可以参考前面的答案:.Net MAUI data binding not carrying through to custom component的数据。