开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜