Binding to a sub-property and updating if any property in chain has changed
While learning MVVM, I've created a DataTemplate
for one of my view models:
<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>
Simplified view model class:
class NodeDefinitionVM : (...)
{
public Point Location
{
get { return model.Location; }
set { model.Location = value; }
}
(...)
}
In my case the model implements INotifyPropertyChanged, because I need to have all changes to model reflected in View (notice Mode=TwoWay
in XAML).
Problem: Initial values of transform offsets (X, Y) are set and I get notifications when 'Location' property changes. However there is no notification that .X has changed and, as I'm binding to Location.X, the transform is not upd开发者_JAVA百科ated (except for the first time), because it expects Location.X change notification. The Point
type is a light-weight struct.
Question: Is it possible to bind to .X, while updating the binding whenever any of the properties along Location.X chain changes? Is there a general solution for a 'longer chain' like Binding prop1.prop2.prop3
?
In general, the binding should update when any property in the chain changes. But this works only when each property in the chain raises PropertyChanged
properly, because there is no way to figure out that something changed otherwise.
For this to work, you would need either to implement INotifyPropertyChanged
on Point
and raise PropertyChanged
when X
or Y
changes, or you need to raise the event for Location
when that happens.
Strangely enough, binding directly to X or Y properties of a TranslateTransform won't work well, although these are DependencyProperties. Following modifications made it work:
<DataTemplate DataType="{x:Type task:NodeDefinitionVM}">
<Ellipse x:Name="ellipse" Width="4" Height="4" Fill="Red"
RenderTransform="{Binding TranslateMatrix}">
</Ellipse>
</DataTemplate>
I needed to create a new 'TranslateMatrix
' property in my ViewModel:
public TranslateTransform TranslateMatrix
{
get
{
var tt = new TranslateTransform(model.Location.X, model.Location.Y);
return tt;
}
}
Finally, the VM needs to publish notifications that the TranslateMatrix
property changes every time Location
the property changes. So the VM listens to model changes and notifies if necessary:
void NodeDefinitionVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Location")
NotifyPropertyChanged(() => TranslateMatrix);
}
There is no way achieve what you're talking about, as much as I'm aware of and met till now in my WPF experience.
As assigning the X
, you jump over actual property.
So you need manually notify do Binding mechanism that property was changed, but how you're gonna figure out that property was changed in your example, if you directly gonna assign value to public field of the struct ?
Regards.
精彩评论