我对WPF动态定位有疑问。
我想根据我在C#中存储的集合中的X和Y坐标将Elipses放在屏幕上。
我已经了解了WPF中使用Windows.Media和Windows.Shapes从C#中创建的绘图功能。
现在我真正想做的是使用这些命名空间在画布中的第一种情况下绘制elipses,所有这些都是在c#中使用我在c#中使用的数据源完成的,以使用x和y坐标来定位elipses。
现在令我困惑的复杂部分是,如果数据源中的数据随着数据库中的数据的变化而改变,我将实现某种例程,每隔几秒检查一次数据库,回退任何数据自上次检索后更改。现在我已经看到了IPropertyChanged接口,我将从我的类中提取,我将其作为页面的数据源公开,因此当我检索更新的数据集时,我可以调用PropertyChanged事件,该事件将通知WPF数据源已更改。
当我最初在C#中将它们放在数据源中的某些项目中时,如何绑定UI中的elipses,这样当数据源发生更改时,elipses会根据需要自动更改以反映更改的数据源,只要ID为每个x和y坐标保持不变。因此,当我将它们设置出来时,我可以为画布中的每个elipse绑定到集合中的特定行吗?
我甚至不知道是否有可能将数据源绑定到Canvas中我可以使用该集合,因为我需要开始但我想我会把这个问题放在那里,因为有人做了类似的事情所以我有一个很好的起点。
由于 伊菲。
答案 0 :(得分:1)
在其他人所说的基础上构建一个完整的自包含示例 - 您可以将其直接复制到kaxaml或xamlpad(或混合,但我认为在这种情况下它必须进入用户控件或窗口的主体)并了解它是如何工作的。
我更喜欢使用画布并设置left和top属性,而不是使用rendertransform,我只是觉得它更具可读性。或者,您可以使用网格并设置边距,但之后您将需要某种值转换器。
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.Resources>
<!-- This is our list of shapes, in this case an inline XML list -->
<XmlDataProvider x:Key="ShapeList">
<x:XData>
<ObjectList xmlns="">
<Shapes>
<shape height="30" width="30" x="50" y="50"/>
<shape height="30" width="40" x="100" y="100"/>
<shape height="30" width="50" x="150" y="150"/>
<shape height="30" width="60" x="200" y="200"/>
<shape height="30" width="70" x="250" y="350"/>
</Shapes>
</ObjectList>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource ShapeList}, XPath=ObjectList/Shapes/*}">
<!-- this template sets the panel as canvas for easy positioning -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- this template defines how each bound item is represented -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="{Binding XPath=@width}" Height="{Binding XPath=@height}">
<Ellipse Fill="White" Stroke="Black" StrokeThickness="2"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<!-- This style positions each bound item's container -->
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding XPath=@x}"/>
<Setter Property="Canvas.Top" Value="{Binding XPath=@y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
您可以绑定到viewmodel上的集合(最佳选择),控件或窗口上的依赖项属性,从代码隐藏中设置资源等,而不是绑定到内联xml列表。
关键是你不应该在C#中布置省略号,除非你绝对必须这样做。将数据提供为某种有意义的对象列表。然后创建一个数据模板,定义数据的表示方式。假设您不必对对象进行任何类型的复杂处理以获得相关的椭圆属性,您应该能够在没有任何代码的情况下执行此操作,或者最多使用一些值转换器。
这种UI分离允许您分别处理更新数据源(业务逻辑)和显示项目(ui)。
所以基本上这个想法是:
答案 1 :(得分:0)
您可以使用平移变换在创建椭圆时定位它们。
TranslateTransform transform = new TranslateTransform();
transform.X = X;
transform.Y = Y;
Ellipse ellipse = new Ellipse();
ellipse.RenderTransform = transform;
...
您可以将省略号存储在字典中,其ID为键,以便快速轻松地检索。
TranslateTransform transform = data[id].RenderTransform as TranslateTransform;
transform.X = newX;
transform.Y = newY;
答案 2 :(得分:0)
如果您的Ellipse对象由类表示,并且可能显示在DataTemplate中,您可以在ItemsControl内完成此操作。
<Ellipse>
<Ellipse.LayoutTransform>
<TranslateTransform X="{Binding XCoord}"
Y="{Binding YCoord}" />
</Ellipse.LayoutTransform>
</Ellipse>
你会choose between LayoutTransform and RenderTransform基于持有Ellipse对象的面板。
我还建议审阅Bea Stollnitz(neéCosta)的一篇文章,该文章展示了如何利用ListBox backed by a Canvas with DataBinding to produce offset objects。很酷。