如何使用 XAML 绑定到 WPF 中的父位置更改且无代码隐藏
我有一个类似 visio 的界面,但某些元素背后有实际的模型数据。用户可以移动元素。
我在画布上使用内容控件,其中元素的视图模型位于内容中,然后可以根据其类型以不同方式显示,但使用相同的内容控件。将视图绑定到视图模型中的不同属性很简单。但是,我必须保存模型中的位置,并且找不到绑定解决方案。
1)Application.Save命令在主视图模型中处理,所以我无权访问那里的视图。这意味着我必须在移动元素时保存位置数据,还是有更好的方法?
2)假设我对1)的看法是正确的,我希望避免代码隐藏,即我不希望内容控件处理它们内容中的元素。然而,到目前为止,代码背后的版本是我能想出的全部:
到目前为止我的代码背后的解决方案:
所有模型元素都实现一个接口:
public interface IViewElement
{
String Position { get; set; }
}
在内容控件中:
void ContentControl_LayoutUpdated(object sender, EventArgs e)
{
IViewElement content = this.Content as IViewElement;
content.Position = new Point(Diagram.GetLeft(this), Diagram.GetTop(this)).ToString();
}
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>
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, i.e. 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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只需封装您在行为中使用的代码隐藏即可
Just encapsulate the codebehind you've used in a Behavior
为什么使用字符串来存储位置?使用一个 Point 或两个小数值,然后使用双向绑定将 ContentControl 的
Canvas.Top
和Canvas.Left
位置绑定到这些值。当顶部和左侧位置发生变化时,它将自动更新模型。
编辑:
这是一个例子:
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
andCanvas.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: