WPF Dynamic Binding X и Y Координаты - PullRequest
2 голосов
/ 11 ноября 2009

У меня вопрос по динамическому позиционированию WPF.

Я хочу разместить Elipses на экране, основываясь на координатах X и Y, которые я сохранил в коллекции в C #.

Мне сообщили о возможности рисования в WPF, которую вы делаете из C # с помощью Windows.Media и Windows.Shapes.

Теперь то, что я на самом деле хочу сделать, - это использовать эти пространства имен, чтобы нарисовать эллипсы в первом случае на холсте, все сделано в c #, используя мой источник данных, который у меня есть в c #, для позиционирования эллипсов с использованием координат x и y.

Теперь сложная часть, которая сбивает меня с толку, заключается в том, что если данные в источнике данных изменяются по мере изменения данных в базе данных, я реализую некоторую процедуру, которая проверяет базу данных каждые несколько секунд, отбрасывая назад любые данные, которые имеют изменено с момента последнего поиска. Теперь я видел интерфейс IPropertyChanged, от которого я унаследую свой класс, который я предоставляю в качестве источника данных для страницы, поэтому при получении обновленного набора данных я могу вызвать событие PropertyChanged, которое уведомит WPF об изменении источника данных.

Как бы я связал эллипсы в пользовательском интерфейсе, когда я первоначально выкладывал их в C #, с определенными элементами из источника данных, чтобы при изменении источника данных эллипсы автоматически изменялись по мере необходимости, чтобы отражать измененный источник данных, пока идентификатор для каждая координата x и y осталась прежней. Так можно ли связывать определенные строки из коллекции для каждого elipse на холсте, когда я их излагаю?

Я даже не знаю, возможно ли связать источник данных с Canvas, внутри которого я могу использовать коллекцию по мере необходимости, но я подумал, что задам этот вопрос, если кто-то сделал что-то подобное, у меня хорошая отправная точка.

Спасибо Сомнительный.

Ответы [ 3 ]

1 голос
/ 13 ноября 2009

Чтобы построить на том, что другие сказали здесь, это полный автономный пример - вы можете скопировать его прямо в kaxaml или xamlpad (или смешать, но я думаю, что в этом случае он должен войти в тело пользовательского контроля или окна ) и посмотрим, как это работает.

Вместо использования rendertransform Я предпочитаю использовать холст и устанавливать свойство left и top, я просто нахожу его более читабельным. Кроме того, вы можете использовать сетку и установить маржу, но тогда вам понадобится какой-нибудь конвертер значений.

<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 вы можете привязать коллекцию к вашей модели представления (лучший выбор), свойство зависимости для вашего элемента управления или окна, установить ресурс из codebehind и т. Д.

Ключевым моментом является то, что вы не должны размечать эллипсы в C #, если вам это абсолютно не нужно. Предоставьте данные в виде своего рода списка значимых объектов. Затем создайте шаблон данных, который определяет, как эти данные представлены. Предполагая, что вам не нужно выполнять какую-либо сложную обработку вашего объекта, чтобы получить соответствующие свойства эллипса, вы сможете сделать это без какого-либо кода или, самое большее, с несколькими преобразователями значений.

Это своего рода разделение пользовательского интерфейса, которое позволяет вам отдельно обновлять источник данных (бизнес-логика) и отображать элементы (пользовательский интерфейс).

Итак, в основном идея такова:

  • Предоставить коллекцию объектов - в моем примере это будет коллекция классов, отражающая структуру элемента формы XML в списке. Это может быть сам бизнес-объект или viewmodel - класс, который оборачивает бизнес-объекты и предоставляет удобно привязываемые свойства (в данном случае, положение и размер). Сама коллекция предпочтительно будет ObservableCollection, чтобы пользовательский интерфейс получал уведомления при добавлении или удалении объектов. Если возможно, добавьте в него данные времени проектирования.
  • Привязка к коллекции с использованием шаблонов данных WPF для определения способа представления элемента. В этом случае я использовал простой ItemsControl с несколькими простыми шаблонами, но это может быть настолько сложным, насколько требуется
  • Определите, как коллекция будет обновляться из исходного источника данных. Если вы правильно настроили предыдущие шаги, это, по сути, отдельная проблема
0 голосов
/ 11 ноября 2009

Вы можете сделать это в DataTemplate , если ваши объекты Ellipse представлены классом и, возможно, отображаются в ItemsControl .

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

Вы бы выбрали между LayoutTransform и RenderTransform в зависимости от панели, на которой находились ваши объекты Ellipse.

Я также рекомендую прочитать статью Беа Штольниц (ne & eacute; Costa), в которой показано, как использовать ListBox , опирающийся на Canvas с DataBinding, для создания смещенных объектов . Очень круто.

0 голосов
/ 11 ноября 2009

Вы можете использовать преобразование translate для позиционирования эллипсов при их создании.

        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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...