简体   繁体   中英

How to bind to parent position changes in WPF using XAML and no code behind

I have a visio-like interfact but have actual model data behind some of the elements. The elements can be moved by the user.

I use a contentcontrol on a canvas whereby the viewmodels of the elements are places in the content which can then be displayed differently depending on their type but using the same contentcontrol. It is simple to bind the view to the different properties in the viewmodel. However, I have to save the position in the model, and I cannot find a binding solution.

1) The Application.Save Command is handled in the main view model, so I do not have access to the view there. That means I must save the postion data when the elements are moved, or is there a better approach?

2) Assuming that I am right with 1), I am looking to avoid code behind, ie I do not want the contentcontrol to deal with the elements that they have in their content. However, so far the code behind version is all I could come up with:

My code behind solution so far:

All model elements implement an interface:

public interface IViewElement
{
    String Position { get; set; }
}

And in the contentcontrol:

 void ContentControl_LayoutUpdated(object sender, EventArgs e)
    {
        IViewElement content = this.Content as IViewElement;
        content.Position = new Point(Diagram.GetLeft(this), Diagram.GetTop(this)).ToString();
    }

The XAML:

<Style TargetType="{x:Type diagram:Item}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type diagram:Item}">
                <Grid Canvas.Top="{Binding ElementName=PART_ContentPresenter, Path=Content.Position, Mode=TwoWay}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                    ContextMenu="{x:Null}">
                    <!-- PART_ContentPresenter -->
                    <ContentPresenter x:Name="PART_ContentPresenter"
                        Content="{TemplateBinding Content}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

<DataTemplate DataType="{x:Type local:ViewModel}">
<StackPanel>
    ...
</StackPanel>

只需封装您在行为中使用的代码隐藏

Why are you using a string to store the position? Use either a Point or two decimal values, and then bind your ContentControl's Canvas.Top and Canvas.Left position to these values using two-way binding.

It will automatically update the model when the Top and Left positions change.

Edit: Here's an example:

<ContentControl Canvas.Top="{Binding ContentModel.Top, Mode=TwoWay}"
                Canvas.Left="{Binding ContentModel.Left, Mode=TwoWay}"
                Content="{Binding ContentModel}" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM