WPF动态绑定X和Y坐标

时间:2009-11-10 22:29:38

标签: wpf binding

我对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中我可以使用该集合,因为我需要开始但我想我会把这个问题放在那里,因为有人做了类似的事情所以我有一个很好的起点。

由于 伊菲。

3 个答案:

答案 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)。

所以基本上这个想法是:

  • 公开一组对象 - 在我的例子中,这将是一个类的集合,它反映了列表中形状xml元素的结构。这可以是业务对象本身,也可以是视图模型 - 一个包装业务对象并公开方便可绑定属性的类(在本例中为position和size)。集合本身最好是ObservableCollection,以便在添加或删除对象时通知UI。如果可能的话,将一些设计时数据投入其中。
  • 使用WPF数据窗口绑定到集合,以定义元素的呈现方式。在这种情况下,我使用了一些简单的ItemsControl和一些简单的模板,但这可能与所需的一样复杂
  • 确定如何从原始数据源更新集合。如果您正确设置了前面的步骤,那么这实际上是一个单独的问题

答案 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。很酷。