我有一个内容视图,该视图具有一个绑定到父级ViewModel的BindableProperty。收到新值时,绑定到BindableProperty的属性将触发一个方法,该方法可在内容视图内以编程方式创建一组新的控件。仅当为父视图设置BindingContext时,才会触发BindableProperty。有人可以告诉我我在做什么错吗?
编辑
看来,更正BindableProperty.Create
中的第三个参数(从typeof(CalendarControlModel)
到typeof(Calendar)
并添加BindingMode.TwoWay,
就可以解决问题。
新问题:为什么在这里需要双向绑定?
后面的内容查看代码
public partial class Calendar
{
public static readonly BindableProperty AppointmentsDataProperty = BindableProperty.Create(nameof(AppointmentsData), typeof(CalendarControlModel), typeof(Calendar), new CalendarControlModel(),BindingMode.TwoWay
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (bindableObject is Calendar view)
{
view.AppointmentsData = (CalendarControlModel)newValue;
}
});
public CalendarControlModel AppointmentsData { get { return (CalendarControlModel)GetValue(AppointmentsDataProperty); } set { SetValue(AppointmentsDataProperty, value); PrepareAppointments(); } }
public Calendar()
{
InitializeComponent();
}
private void PrepareAppointments()
{
....
MainScrollView.Content = meetingsGrid;
}
内容视图
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="NS.Controls.Calendar">
<ContentView.Content>
<ScrollView x:Name="MainScrollView">
</ScrollView>
</ContentView.Content>
</ContentView>
查看模型
class CalendarPageViewModel : BaseViewModel
{
private DailyCalendarControlModel appointmentsData;
public ObservableCollection<PickerModel> AppointmentTypes { get; set; }
public DailyCalendarControlModel AppointmentsData
{
get => appointmentsData;
set => SetProperty(ref appointmentsData, value);
}
public PickerModel SelectedAppointmentType { get; set; }
public CalendarSummaryModel Summary { get; set; }
public ICommand SwitchDayCommand { get; set; }
public ICommand SwitchAppointmentType { get; set; }
public DailyCalendarPageViewModel()
{
SwitchDayCommand = new Command<DateTime>(date =>
{
if (date.Day % 2 == 1)
{
AppointmentsData = new DailyCalendarControlModel
{
Appointments = DataGenerators.GenerateAppointmentsList1(),
Schedule = DataGenerators.GenerateSchedule()
};
}
else
{
AppointmentsData = new DailyCalendarControlModel
{
Appointments = DataGenerators.GenerateAppointmentsList2(),
Schedule = DataGenerators.GenerateSchedule()
};
}
});
SwitchAppointmentType = new Command<int>(type =>
{
});
}
}
父页面浏览量
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:controls="clr-namespace:NS.Controls;assembly=NS"
mc:Ignorable="d"
x:Class="NS.Views.CalendarPage">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<controls:PageHeader NextDayCommand="{Binding SwitchDayCommand}" PreviousDayCommand="{Binding SwitchDayCommand}" ChangedTypeCommand="{Binding SwitchAppointmentType}" />
<controls:Calendar x:Name="CalendarControl" AppointmentsData="{Binding AppointmentsData}" Grid.Row="1" />
<controls:CalendarSummary Summary="{Binding Summary}" Grid.Row="2" />
</Grid>
</ContentPage.Content>
</ContentPage>
父页面背后的代码
public partial class CalendarPage : ContentPage
{
public CalendarPage()
{
InitializeComponent();
var appointmentTypes = EnumFactories.CreateFromEventType();
CalendarPageViewModel model = new CalendarPageViewModel
{
SelectedAppointmentType = appointmentTypes.FirstOrDefault(a => a.Id == (int)EventType.Consultation),
AppointmentTypes = appointmentTypes,
//SelectedDate = DateTime.Now.Date,
AppointmentsData = new CalendarControlModel {Appointments = DataGenerators.GenerateAppointmentsList(), Schedule = DataGenerators.GenerateSchedule() },
Summary = new CalendarSummaryModel
{
AppointmentsSummaries = $"Cabinet1",
TotalAppointments = "5",
TotalSum = "1"
}
};
BindingContext = model;
}
protected override void OnAppearing()
{
base.OnAppearing();
CalendarControl.ScrollToCurrentTime();
}
}
答案 0 :(得分:1)
public static readonly BindableProperty AppointmentsDataProperty = BindableProperty.Create(nameof(AppointmentsData), typeof(CalendarControlModel), typeof(CalendarControlModel), new CalendarControlModel(),
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (bindableObject is Calendar view)
{
view.AppointmentsData = (CalendarControlModel)newValue;
}
});
nameof(AppointmentsData):这提供了存储信息的属性的名称。
typeof(CalendarControlModel)::这是属性的类型。
typeof(CalendarControlModel)::这是属性所在类的类型。
新的CalendarControlModel():这只是默认值。
似乎您为第三个属性设置了错误的值
此外,您应该直接在PropertyChanged中设置UI,否则需要将绑定模式设置为 TwoWay
因此,请按照以下说明改进代码
public static readonly BindableProperty AppointmentsDataProperty = BindableProperty.Create(nameof(AppointmentsData), typeof(CalendarControlModel), typeof(Calendar), new CalendarControlModel(),BindingMode.OneWay,
propertyChanged: (bindableObject, oldValue, newValue) =>
{
if (bindableObject is Calendar view)
{
var model = newValue as CalendarControlModel;
var label = new Label { Text = $"{model.Hour}:{model.Minute}", HorizontalTextAlignment = TextAlignment.Center, FontSize = 32 };
view.MainScrollView.Content = label;
}
});