在学习MVVM时,我为我的一个视图模型创建了DataTemplate
:
<DataTemplate DataType="{x:Type task:NodeDefinitionVM}">
<Ellipse Width="4" Height="4" Fill="Red" >
<Ellipse.RenderTransform>
<TranslateTransform X="{Binding Location.X, Mode=TwoWay}"
Y="{Binding Location.Y, Mode=TwoWay}" />
</Ellipse.RenderTransform>
</Ellipse>
</DataTemplate>
简化视图模型类:
class NodeDefinitionVM : (...)
{
public Point Location
{
get { return model.Location; }
set { model.Location = value; }
}
(...)
}
在我的情况下,模型实现了INotifyPropertyChanged,因为我需要对View中反映的模型进行所有更改(在XAML中注意Mode=TwoWay
)。
问题:设置了转换偏移(X,Y)的初始值,当“位置”属性发生变化时,我会收到通知。但是没有通知 .X 已更改,并且由于我绑定到Location.X,因此转换不会更新(第一次除外),因为它期望Location.X更改通知。 Point
类型是轻量级结构。
问题:当 Location.X 链中的任何属性发生变化时,是否可以绑定到.X,同时更新绑定?是否有Binding prop1.prop2.prop3
这样的“较长链”的通用解决方案?
答案 0 :(得分:2)
通常,绑定应在链中的任何属性更改时更新。但这只适用于链中的每个属性正确引发PropertyChanged
,因为没有办法弄清楚某些事情会发生变化。
为了实现这一点,您需要在INotifyPropertyChanged
上实施Point
并在PropertyChanged
或X
更改时提升Y
,或者您需要当发生这种情况时,提升Location
的事件。
答案 1 :(得分:2)
奇怪的是,直接绑定到TranslateTransform的X或Y属性将无法正常工作,尽管这些是DependencyProperties。以下修改使其有效:
<DataTemplate DataType="{x:Type task:NodeDefinitionVM}">
<Ellipse x:Name="ellipse" Width="4" Height="4" Fill="Red"
RenderTransform="{Binding TranslateMatrix}">
</Ellipse>
</DataTemplate>
我需要在ViewModel中创建一个新的“TranslateMatrix
”属性:
public TranslateTransform TranslateMatrix
{
get
{
var tt = new TranslateTransform(model.Location.X, model.Location.Y);
return tt;
}
}
最后,VM需要发布TranslateMatrix
属性每次Location
属性更改时发生更改的通知。因此,VM会监听模型更改并在必要时通知:
void NodeDefinitionVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Location")
NotifyPropertyChanged(() => TranslateMatrix);
}
答案 2 :(得分:1)
在我的WPF体验中,没有办法达到你所说的,就像我所知道的那样,直到现在还没有。
在分配X
时,您会跳过实际属性。
因此,您需要手动通知do Binding机制,该属性已更改,但如果您直接将值分配给公共 field ,您将如何确定该示例中的属性已更改结构?
问候。