【问题标题】:WPF Dynamic Binding X and Y Co-ordinatesWPF 动态绑定 X 和 Y 坐标
【发布时间】:2011-08-26 23:50:52
【问题描述】:

我有一个关于 WPF 动态定位的问题。

我想根据存储在 C# 集合中的 X 和 Y 坐标将省略号放置在屏幕上。

我已经了解到 WPF 中的绘图功能,您可以使用 Windows.Media 和 Windows.Shapes 在 C# 中进行绘图。

现在我真正想要做的是使用这些命名空间在第一种情况下在画布中绘制省略号,所有这些都在 c# 中完成,使用我在 c# 中的数据源来使用 x 和 y 坐标定位省略号。

现在让我感到困惑的复杂部分是,如果数据源中的数据随着数据库中的数据变化而变化,我将实施某种例程,每隔几秒钟检查一次数据库,拉回任何具有自上次检索后更改。现在我已经看到了 IPropertyChanged 接口,我将从我的类继承该接口,我将其作为页面的数据源公开,因此当我检索更新的数据集时,我可以调用 PropertyChanged 事件,该事件将通知 WPF 数据源已更改。

当我最初在 C# 中将省略号布局到数据源中的某些项目时,我如何将它们绑定到 UI 中,这样当数据源更改时,只要 ID每个 x 和 y 坐标保持不变。那么当我设置它们时,我可以为画布中的每个椭圆绑定到集合中的特定行吗?

我什至不知道是否有可能将数据源绑定到 Canvas,我可以在其中使用我需要的集合,但我想我会把这个问题放在那里,以防有人做过类似的事情所以我有一个很好的起点。

谢谢 好不好。

【问题讨论】:

    标签: wpf binding


    【解决方案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>
    

    您可以绑定到视图模型上的集合(最佳选择)、控件或窗口上的依赖项属性、从代码隐藏设置资源等,而不是绑定到内联 xml 列表。

    关键点是你不应该在 C# 中布置省略号,除非你绝对必须这样做。以某种有意义的对象列表的形式提供数据。然后创建一个数据模板来定义该数据的表示方式。假设您不必对对象进行任何复杂的处理即可获得相关的椭圆属性,您应该无需任何代码或最多使用几个值转换器即可完成此操作。

    这是一种 UI 分离,允许您分别处理更新数据源(业务逻辑)和显示项目 (ui)。

    所以基本上这个想法是:

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

    【讨论】:

      【解决方案2】:

      您可以在创建椭圆时使用平移变换来定位它们。

              TranslateTransform transform = new TranslateTransform();
              transform.X = X;
              transform.Y = Y;
              Ellipse ellipse = new Ellipse();
              ellipse.RenderTransform = transform;
              ...
      

      您可以将省略号存储在字典中,并将其作为键,以便快速轻松地检索。

              TranslateTransform transform = data[id].RenderTransform as TranslateTransform;
              transform.X = newX;
              transform.Y = newY;
      

      【讨论】:

      • 这是一种老式的做法,非常winforms。真的没有必要在代码中创建或摆弄像这样的基本形状。
      【解决方案3】:

      如果您的 Ellipse 对象由一个类表示,并且可能显示在 ItemsControl 中,您可以在 DataTemplate 中完成此操作。

      <Ellipse>
          <Ellipse.LayoutTransform>
              <TranslateTransform X="{Binding XCoord}"
                                  Y="{Binding YCoord}" />
          </Ellipse.LayoutTransform>
      </Ellipse>
      

      你会choose between LayoutTransform and RenderTransform 基于你的椭圆对象的面板。

      我还建议查看 Bea Stollnitz(neé Costa)的一篇文章,该文章展示了如何利用 ListBox backed by a Canvas with DataBinding to produce offset objects。很酷。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        相关资源
        最近更新 更多