在加载时触发的Xamarin TimePicker propertychanged事件

时间:2016-11-12 23:40:21

标签: android xamarin xamarin.forms timepicker propertychanged

我正在使用Xamarin表单为Android创建一个Xamarin应用程序来创建我的布局。我遇到了一个问题,我的时间选择器在加载我的视图单元时触发。

我正在做的是创建列表视图,然后将项目模板设置为我的自定义视图单元格模板。在我的视图单元格模板中,我创建了一个TimePicker并将PropertyChanged事件绑定到它。我还使用从数据库中检索的信息设置TimePicker.Time属性。此时似乎发生的事情是我的PropertyChanged事件将针对将在列表视图中显示的每个项目触发。这导致不需要多个数据库调用。

有没有办法在实际更改属性之前停止调用PropertyChanged事件?

我的代码如下。

public class MyCell : ViewCell
{
private readonly TimePicker _myTimePicker;
public MyCell()
{
   _myTimePicker = new TimePicker()
        {
            HorizontalOptions = LayoutOptions.EndAndExpand
        };

        _myTimePicker.SetBinding(TimePicker.TimeProperty, "StartTime");
        _myTimePicker.PropertyChanged += MyTimePicker_PropertyChanged;

        var viewLayout = new StackLayout()
        {
            HorizontalOptions = LayoutOptions.StartAndExpand,
            Orientation = StackOrientation.Horizontal,
            Padding = new Thickness(20),
            Children = { _myTimePicker }
        };
        View = viewLayout;
}

private void MyTimePicker_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == TimePicker.TimeProperty.PropertyName && _myTimePicker.Time != TimeSpan.MinValue)
        {
            var dataAccess = new DataAccessLayer();
            dataAccess.Update(myTimePicker.Time);
        }
    }
}

我不确定为什么会多次触发propertychanged事件,以及如何在实际选择时间之前停止触发。任何帮助将不胜感激。

下面是我显示列表视图的表单代码。我的所有xaml都是在代码中定义的。 'MyCell'使用'_dataAccess.GetTimes()'返回的值。

public class TimeDetails : ContentPage
{
    private ListView _listView;
    private readonly DataAccessLayer _dataAccess = new DataAccessLayer();

    protected override void OnAppearing()
    {
        _listView = new ListView
        {
            RowHeight = 80,
            SeparatorColor = Color.Blue,
            SeparatorVisibility = SeparatorVisibility.Default
        };

        _listView.ItemsSource = _dataAccess.GetTimes();
        _listView.ItemTemplate = new DataTemplate(typeof(MyCell));
        _listView.ItemSelected += ListView_ItemSelected;

        Content = new StackLayout
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            Children = { _listView }
        };
    }
}

_dataAcess.GetTimes()的返回类型是TaskTime的List。 TaskTime模型如下所示。

public class TaskTime
{
    public int Id { get; set; }
    public string Task { get; set; }
    public TimeSpan StartTime { get; set; }
}

2 个答案:

答案 0 :(得分:1)

class MyCell : ViewCell
{
    private readonly TimePicker _myTimePicker;
    public MyCell()
    {
        _myTimePicker = new TimePicker()
        {
            HorizontalOptions = LayoutOptions.EndAndExpand
        };

        _myTimePicker.SetBinding(TimePicker.TimeProperty, "StartTime");
        _myTimePicker.PropertyChanged += MyTimePicker_PropertyChanged;
        _myTimePicker.Focused += _myTimePicker_Focused;

        var viewLayout = new StackLayout()
        {
            HorizontalOptions = LayoutOptions.StartAndExpand,
            Orientation = StackOrientation.Horizontal,
            Padding = new Thickness(20),
            Children = { _myTimePicker }
        };
        View = viewLayout;
    }

    bool myTimePickerSelected;
    private void _myTimePicker_Focused(object sender, FocusEventArgs e)
    {
        myTimePickerSelected = true;
    }

    private void MyTimePicker_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {

        if (e.PropertyName == TimePicker.TimeProperty.PropertyName && myTimePickerSelected)
        {
            //var dataAccess = new DataAccessLayer();
            //dataAccess.Update(myTimePicker.Time);
        }
    }
}

答案 1 :(得分:0)

使用焦点和非焦点事件的更简单解决方案是:

public class CustomTimePicker : TimePicker
{
    public event EventHandler TimeChanged;

    private TimeSpan StartValue { get; set; }

    public CustomTimePicker ()
    {
        this.Focused += OnFoused;
        this.Unfocused += OnUnfocused;
    }

    private void OnFoused(object sender, FocusEventArgs e)
    {
        StartValue = this.Time;
    }

    private void OnUnfocused(object sender, FocusEventArgs e)
    {
        if (StartValue != this.Time)
        {
            TimeChanged?.Invoke(this, e);
        }
    }
}