如何防止将 2 个属性设置在一起而调用一个方法两次
How to prevent setting 2 properties together from calling a method twice
我在 ViewModel 上有 2 个属性:DateFrom 和 DateTo。
我想在其中一个更改时调用 RefreshProducts() (例如,由最终用户或以编程方式更改),这已实现如下:
public DateTime? DateFrom
{
get { return _dateFrom; }
set
{
_dateFrom = value;
RaisePropertyChanged("DateFrom");
RefreshProducts();
}
}
public DateTime? DateTo
{
get { return _dateTo; }
set
{
_dateTo = value;
RaisePropertyChanged("DateTo");
RefreshProducts();
}
}
private void RefreshProducts()
{
//...
}
private void SetThisWeek()
{
DateFrom = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
DateTo = DateTime.Today.AddDays(6-(int)DateTime.Today.DayOfWeek);
}
但是,我的问题在于,如果同时更改两个属性(例如 SetThisWeek() 方法),则会调用 RefreshProducts 两次;如您所料,每个属性一次。
我的问题是:什么是最好的方法来防止同时设置两个属性时调用 RefreshProducts(),例如在 SetThisWeek() 方法中?
我试过使用 bool 来帮助管理这个,例如...
bool CanRefresh = true;
public DateTime? DateFrom
{
get { return _dateFrom; }
set
{
_dateFrom = value;
RaisePropertyChanged("DateFrom");
if (CanRefresh) RefreshProducts();
}
}
public DateTime? DateTo { ... }
private void RefreshProducts() { ... }
private void SetThisWeek()
{
CanRefresh = false;
DateFrom = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
DateTo = DateTime.Today.AddDays(6-(int)DateTime.Today.DayOfWeek);
CanRefresh = true;
RefreshProducts();
}
这很好用,但是我不喜欢以这种方式使用 bool,而且我也不喜欢使用它所需的 "noise" 代码。管理 bool 允许在将来修改程序时出现潜在的错误......我正在寻找一种更简洁的方法来处理这个问题。
您是否有充分的理由无法更新 SetThisWeek
方法中的私有支持字段?:-
public DateTime? DateFrom
{
get { return _dateFrom; }
set
{
_dateFrom = value;
RaisePropertyChanged("DateFrom");
RefreshProducts();
}
}
public DateTime? DateTo
{
get { return _dateTo; }
set
{
_dateTo = value;
RaisePropertyChanged("DateTo");
RefreshProducts();
}
}
private void SetThisWeek()
{
_dateFrom = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
RaisePropertyChanged("DateFrom");
_dateTo = DateTime.Today.AddDays(6-(int)DateTime.Today.DayOfWeek);
RaisePropertyChanged("DateTo");
RefreshProducts();
}
或者,如果重复 RaisePropertyChanged
调用冒犯了您(这冒犯了我!),您可以考虑使用 AoP 自动执行此操作(例如 PostSharp or Mono.Cecil)。对于这个简单的例子来说,这将是一个非常核心的解决方案——IL 编织不适合胆小的人! - 但它可以帮助在更现实的场景中简化事情。
在我看来,您最好的两个选择是:
- 接受它。没有看到
RefreshProducts()
做了什么,不清楚调用它两次有多糟糕。但在我习惯看到的其他类似场景中,这通常不是一个大问题。
- 提供一个 setter 方法,该方法将两个值都作为参数并设置两个值 "atomically"(在您刷新的意义上)。
即
public void SetDatesFromAndTo(DateTime? from, DateTime? to)
{
// Update private values here
// Then...
RefreshProducts();
}
请注意,您的 SetThisWeek()
方法本质上就是这种机制,尽管目前它直接设置属性而不是支持字段。
我从您添加的详细信息中了解到,您担心保留用户单独更新属性的能力。但这并不难实现。您的聚合 setter(例如我展示的 SetDatesFromAndTo()
方法,或您的 SetThisWeek()
)可以引发 属性-changed 事件,就像 属性 setter可以。因此,不是设置属性,而是设置支持字段并引发事件。
我在 ViewModel 上有 2 个属性:DateFrom 和 DateTo。
我想在其中一个更改时调用 RefreshProducts() (例如,由最终用户或以编程方式更改),这已实现如下:
public DateTime? DateFrom
{
get { return _dateFrom; }
set
{
_dateFrom = value;
RaisePropertyChanged("DateFrom");
RefreshProducts();
}
}
public DateTime? DateTo
{
get { return _dateTo; }
set
{
_dateTo = value;
RaisePropertyChanged("DateTo");
RefreshProducts();
}
}
private void RefreshProducts()
{
//...
}
private void SetThisWeek()
{
DateFrom = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
DateTo = DateTime.Today.AddDays(6-(int)DateTime.Today.DayOfWeek);
}
但是,我的问题在于,如果同时更改两个属性(例如 SetThisWeek() 方法),则会调用 RefreshProducts 两次;如您所料,每个属性一次。
我的问题是:什么是最好的方法来防止同时设置两个属性时调用 RefreshProducts(),例如在 SetThisWeek() 方法中?
我试过使用 bool 来帮助管理这个,例如...
bool CanRefresh = true;
public DateTime? DateFrom
{
get { return _dateFrom; }
set
{
_dateFrom = value;
RaisePropertyChanged("DateFrom");
if (CanRefresh) RefreshProducts();
}
}
public DateTime? DateTo { ... }
private void RefreshProducts() { ... }
private void SetThisWeek()
{
CanRefresh = false;
DateFrom = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
DateTo = DateTime.Today.AddDays(6-(int)DateTime.Today.DayOfWeek);
CanRefresh = true;
RefreshProducts();
}
这很好用,但是我不喜欢以这种方式使用 bool,而且我也不喜欢使用它所需的 "noise" 代码。管理 bool 允许在将来修改程序时出现潜在的错误......我正在寻找一种更简洁的方法来处理这个问题。
您是否有充分的理由无法更新 SetThisWeek
方法中的私有支持字段?:-
public DateTime? DateFrom
{
get { return _dateFrom; }
set
{
_dateFrom = value;
RaisePropertyChanged("DateFrom");
RefreshProducts();
}
}
public DateTime? DateTo
{
get { return _dateTo; }
set
{
_dateTo = value;
RaisePropertyChanged("DateTo");
RefreshProducts();
}
}
private void SetThisWeek()
{
_dateFrom = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
RaisePropertyChanged("DateFrom");
_dateTo = DateTime.Today.AddDays(6-(int)DateTime.Today.DayOfWeek);
RaisePropertyChanged("DateTo");
RefreshProducts();
}
或者,如果重复 RaisePropertyChanged
调用冒犯了您(这冒犯了我!),您可以考虑使用 AoP 自动执行此操作(例如 PostSharp or Mono.Cecil)。对于这个简单的例子来说,这将是一个非常核心的解决方案——IL 编织不适合胆小的人! - 但它可以帮助在更现实的场景中简化事情。
在我看来,您最好的两个选择是:
- 接受它。没有看到
RefreshProducts()
做了什么,不清楚调用它两次有多糟糕。但在我习惯看到的其他类似场景中,这通常不是一个大问题。 - 提供一个 setter 方法,该方法将两个值都作为参数并设置两个值 "atomically"(在您刷新的意义上)。
即
public void SetDatesFromAndTo(DateTime? from, DateTime? to)
{
// Update private values here
// Then...
RefreshProducts();
}
请注意,您的 SetThisWeek()
方法本质上就是这种机制,尽管目前它直接设置属性而不是支持字段。
我从您添加的详细信息中了解到,您担心保留用户单独更新属性的能力。但这并不难实现。您的聚合 setter(例如我展示的 SetDatesFromAndTo()
方法,或您的 SetThisWeek()
)可以引发 属性-changed 事件,就像 属性 setter可以。因此,不是设置属性,而是设置支持字段并引发事件。