Rys*_*gan 7 c# wpf design-patterns
为了简单说明我的困境,让我说我有以下代码:
class A
{
// May be set by a code or by an user.
public string Property
{
set { PropertyChanged(this, EventArgs.Empty); }
}
public EventHandler PropertyChanged;
}
class B
{
private A _a;
public B(A a)
{
_a = a;
_a.PropertyChanged += Handler;
}
void Handler(object s, EventArgs e)
{
// Who changed the Property?
}
public void MakeProblem()
{
_a.Property = "make a problem";
}
}
Run Code Online (Sandbox Code Playgroud)
为了履行其职责,B级必须对A的PropertyChanged事件作出反应,但在某些情况下也能够自行交替该属性.不幸的是,其他对象也可以与Property进行交互.
我需要一个顺序流的解决方案.也许我可以使用一个变量来禁用一个动作:
bool _dontDoThis;
void Handler(object s, EventArgs e)
{
if (_dontDoThis)
return;
// Do this!
}
public void MakeProblem()
{
_dontDoThis = true;
_a.Property = "make a problem";
_dontDoThis = false;
}
Run Code Online (Sandbox Code Playgroud)
有更好的方法吗?
解决的子弹越多越好.
我最初的问题是TextBox(WPF),我想根据其内容和焦点进行补充.所以我需要对TextChanged事件作出反应,如果它的来源是从我的补充中派生的,我还需要省略该事件.在某些情况下,不应通知TextChanged事件的其他侦听器.某些状态和样式的某些字符串对其他人不可见.
我找到了一种关于与该财产相关的第三方的解决方案,我们不想在该财产发生变化时通知他们。
但有以下要求:
解决办法是将A替换为MyA,如下:
class A
{
// May be set by a code or by an user.
public string Property
{
set { OnPropertyChanged(EventArgs.Empty); }
}
// This is required
protected virtual void OnPropertyChanged(EventArgs e)
{
PropertyChanged(this, e);
}
public EventHandler PropertyChanged;
}
// Inject MyA instead of A
class MyA : A
{
private bool _dontDoThis;
public string MyProperty
{
set
{
try
{
_dontDoThis = true;
Property = value;
}
finally
{
_dontDoThis = false;
}
}
}
protected override void OnPropertyChanged(EventArgs e)
{
// Also third parties will be not notified
if (_dontDoThis)
return;
base.OnPropertyChanged(e);
}
}
class B
{
private MyA _a;
public B(MyA a)
{
_a = a;
_a.PropertyChanged += Handler;
}
void Handler(object s, EventArgs e)
{
// Now we know, that the event is not raised by us.
}
public void MakeProblem()
{
_a.MyProperty = "no problem";
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是我们仍然使用 back bool 字段并且我们假设单个线程。为了摆脱第一个,我们可以使用EZSlaver建议的重构解决方案(此处)。首先,创建一个一次性包装纸:
class Scope
{
public bool IsLocked { get; set; }
public static implicit operator bool(Scope scope)
{
return scope.IsLocked;
}
}
class ScopeGuard : IDisposable
{
private Scope _scope;
public ScopeGuard(Scope scope)
{
_scope = scope;
_scope.IsLocked = true;
}
public void Dispose()
{
_scope.IsLocked = false;
}
}
Run Code Online (Sandbox Code Playgroud)
然后 MyProperty 可能会重构为:
private readonly Scope _dontDoThisScope = new Scope();
public string MyProperty
{
set
{
using (new ScopeGuard (_dontDoThisScope))
Property = value;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
697 次 |
| 最近记录: |