Xamarin TimePicker propertychanged 事件在加载时触发
Xamarin TimePicker propertychanged event fired on load
我正在为 android 开发一个 Xamarin 应用程序,使用 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);
}
}
}
我不确定为什么 属性changed 事件会被触发多次,以及在我实际选择时间之前如何停止它触发。任何帮助将不胜感激。
下面是我用于显示列表视图的表单的代码。我所有的 xaml 都是在代码中定义的。 'MyCell' 使用来自“_dataAccess.GetTimes()”的 return 值。
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 }
};
}
}
return类型的_dataAcess.GetTimes()是TaskTime的List。 TaskTime 模型如下所示。
public class TaskTime
{
public int Id { get; set; }
public string Task { get; set; }
public TimeSpan StartTime { get; set; }
}
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);
}
}
}
使用聚焦事件和非聚焦事件的更简单的解决方案是:
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);
}
}
}
我看到的是 OnAppearing()
在所有初始化完成后完成。也许您可以引入一个布尔变量,然后在 PropertyChanged()
方法中使用它。这是一个技巧,因为您必须从 ContentPage
开始,并在初始化完成时将一个值传递给您的控件。
我刚刚看到,CellView 中有 OnAppearing()
方法,这样一切都在您的控制中 class.
我正在为 android 开发一个 Xamarin 应用程序,使用 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);
}
}
}
我不确定为什么 属性changed 事件会被触发多次,以及在我实际选择时间之前如何停止它触发。任何帮助将不胜感激。
下面是我用于显示列表视图的表单的代码。我所有的 xaml 都是在代码中定义的。 'MyCell' 使用来自“_dataAccess.GetTimes()”的 return 值。
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 }
};
}
}
return类型的_dataAcess.GetTimes()是TaskTime的List。 TaskTime 模型如下所示。
public class TaskTime
{
public int Id { get; set; }
public string Task { get; set; }
public TimeSpan StartTime { get; set; }
}
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);
}
}
}
使用聚焦事件和非聚焦事件的更简单的解决方案是:
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);
}
}
}
我看到的是 OnAppearing()
在所有初始化完成后完成。也许您可以引入一个布尔变量,然后在 PropertyChanged()
方法中使用它。这是一个技巧,因为您必须从 ContentPage
开始,并在初始化完成时将一个值传递给您的控件。
我刚刚看到,CellView 中有 OnAppearing()
方法,这样一切都在您的控制中 class.