我有一个属性BindableCollection<Cat> { get; private set; }
,其中有许多Cat
个对象绑定到我的WPF XAML中的ItemsControl。
然后我将以下代码附加到此ItemsControl中的按钮。
XAML代码段
<Button Content="Pat Cat" cal:Message.Attach="PatCat($dataContext)" />
在ViewModel中......
BindableCollection<Cat> { get; private set; }
public bool CanPatCat(Cat cat)
{
return cat.Pattable && cat.Alive;
}
public void PatCat(Cat cat)
{
// pat the cat
cat.Alive = false;
}
鉴于这是一个方法保护而不是属性,如何通知UI以便为BindableCollection中的每个Cat评估CanPat方法,因为一旦Cat被拍了,保护方法现在将返回false?
答案 0 :(得分:1)
虽然对于属性存在特定且复杂的UI感知机制(我在谈论Binding),但对于方法,情况完全不同。 在我的拙见中使用这种情况下的事件是不合适的,所以我想到了一个基于扩展Caliburn Micro框架的解决方案。
首先,我们需要创建一个特定的ActionMessage,用于在调用后重新执行guard方法。我称之为RefreshableActionMessage
。
public class RefreshableActionMessage : ActionMessage
{
private bool refreshAfterInvoke = true;
public bool RefreshAfterInvoke
{
get { return refreshAfterInvoke; }
set { refreshAfterInvoke = value; }
}
}
现在我们必须在我们的“看守”按钮中使用它(是的,我们需要使用详细的语法):
<Button Content="Pat Cat">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<local:RefreshableActionMessage MethodName="PatCat">
<cal:Parameter Value="{Binding}" />
</local:RefreshableActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
缺少负责重新执行guard方法的代码,但我们可以在Configure
类的Bootstrapper
方法中添加它:
protected override void Configure()
{
ActionMessage.InvokeAction = delegate(ActionExecutionContext context)
{
RefreshableActionMessage refreshableActionMessage;
object[] parameters = MessageBinder.DetermineParameters(context, context.Method.GetParameters());
object obj = context.Method.Invoke(context.Target, parameters);
Task task = obj as Task;
if (task != null)
{
obj = task.AsResult();
}
IResult result = obj as IResult;
if (result != null)
{
obj = new IResult[]
{
result
};
}
IEnumerable<IResult> enumerable = obj as IEnumerable<IResult>;
if (enumerable != null)
{
obj = enumerable.GetEnumerator();
}
IEnumerator<IResult> enumerator = obj as IEnumerator<IResult>;
if (enumerator != null)
{
Coroutine.BeginExecute(enumerator, new CoroutineExecutionContext
{
Source = context.Source,
View = context.View,
Target = context.Target
}, null);
}
refreshableActionMessage = context.Message as RefreshableActionMessage;
if (refreshableActionMessage != null && refreshableActionMessage.RefreshAfterInvoke)
{
refreshableActionMessage.UpdateAvailability();
}
};
}
如您所见,如果自定义ActionMessage
需要刷新,则可以通过调用UpdateAvailability
方法执行。
我希望这个解决方案可以帮到你。
答案 1 :(得分:0)
我最终为每只Cat创建了一个单独的ViewModel,因此CatViewModel具有相应的CatView。然后,我能够通知可绑定集合已经更改,并且事情按预期工作。
注意,我错误地将ViewModel逻辑放入我的Cat模型中。这些是我的模型正在改变的属性。我把它们移到了CatViewModel。