【问题标题】:BindableProperty firing only onceBindableProperty 只触发一次
【发布时间】:2020-07-23 03:47:11
【问题描述】:

我有一个内容视图,它有一个绑定到父视图模型的 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();
    }
}

【问题讨论】:

  • 我无法从您的代码中找到原因。您可以提供一个包含问题的示例,以便我可以在我这边进行测试。
  • @LucasZhang-MSFT 我会准备一个样本。我应该把它/发送到哪里?感谢您的帮助。
  • 你可以发到github上。
  • @LucasZhang-MSFT 我在 github github.com/cristiproj/CalendarSampleProblem 上添加了一个示例项目。再次感谢!

标签: mvvm xamarin.forms


【解决方案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) :这是属性所在类的类型。

new 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;



                }
            });

【讨论】:

    猜你喜欢
    • 2021-03-22
    • 2015-09-07
    • 2016-11-10
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多