ItemsControl (виртуализировать информацию о футболе) - PullRequest
0 голосов
/ 11 октября 2011

Я пытаюсь эмулировать схему дисков NFL для визуализации некоторых данных дисков из игры.Пример того, что я грубо пытаюсь подражать, можно увидеть здесь, благодаря nfl.com.Я пытаюсь добиться следующего:

  • Отображение игрового поля
  • Рисование данных поверх игрового поля
  • Когда я наводю курсор мыши на что-то,затем я хочу запустить событие (например, всплывающую подсказку)

http://www.nfl.com/gamecenter/2011100909/2011/REG5/jets@patriots#menu=drivechart

Вот где я сейчас, прежде всего xaml:

<StackPanel x:Name="myStackPanel" Orientation="Vertical">
  <StackPanel.Background>
    <ImageBrush ImageSource="{StaticResource PlayingField}" Stretch="Fill" />
  </StackPanel.Background>
  <ItemsControl Background="AliceBlue" Opacity="0.5" 
                ItemsSource="{Binding Path=DriveDetails}"           
                ItemTemplate="{StaticResource myDataTemplate}" 
                ItemsPanel="{StaticResource myItemsPanelTemplate}" />
</StackPanel>

Результат:

(Извините, я новичок, не могу добавить скриншот!)

Я приложу все усилия, чтобы описать то, что я вижу, я уверен, что большинство из вас поймет это после прочтения xaml.В основном я вижу футбольное поле на заднем плане и в левом верхнем углу - мой элемент ItemsControl.

StackPanel не требует пояснений, теперь я столкнулся с проблемамиизображение с изменением размера в один ярд не представляет один пиксель, но я оставлю это на следующий день, моя главная задача - как я могу визуализировать данные.Кроме того, визуализация диска не должна начинаться в верхнем левом углу: D Так что, имея дело только с ItemsControl, я остаюсь с этим:

(Извините, я новичок, яне могу добавить скриншот!)

Еще раз, я попытаюсь описать изображение.Это крупный план вышеупомянутого элемента управления ItemsControl, без фонового изображения (футбольного поля).

Примечание. Фон ItemsControl был установлен на AliceBlue, чтобы его было легче увидеть.будет прозрачным, как только у меня будет эта работа.

ItemsSource связан со списком класса «Play»:

public class Play
{
  public int Quarter { get; set; }
  public int Result { get; set; }
  public PlayType TypeOfPlay { get; set; }
  public double WidthOfPlay { get; set; }
}

PlayType - это перечисление:

public enum PlayType
{
  Run,
  Pass,
  Penalty,
  Punt,
  FieldGoal
}

Список получает некоторые данные… (примерные данные, я знаю, что 1-й даун получен lol)

List<Play> SamplePlays = new List<Play>()
{
  new Play { Quarter = 1, Result = 5, TypeOfPlay = PlayType.Penalty, WidthOfPlay = 30 },
  new Play { Quarter = 1, Result = 5, TypeOfPlay = PlayType.Run, WidthOfPlay = 30 },
  new Play { Quarter = 1, Result = 5, TypeOfPlay = PlayType.Pass, WidthOfPlay = 30 },
  new Play { Quarter = 1, Result = 40, TypeOfPlay = PlayType.Punt, WidthOfPlay = 240 }
};

… и передается с помощью класса параметров передачи вViewModel…

ucHomeInstance = ucDriveChartInstance;
((ucDriveChart)ucHomeInstance).setViewModel(new ucDriveChartVM(new ucDriveChartTP() 
  { Plays = SamplePlays }));

… где он назначен свойству DriveDetails

public class ucDriveChartVM : ViewModelBase
{
    public List<Play> DriveDetails { get; set; }

    public ucDriveChartVM(ucDriveChartTP transferParameter)
    {
        this.DriveDetails = transferParameter.Plays;
    }
}

Вот xaml для ItemsPanel:

<ItemsPanelTemplate x:Key="myItemsPanelTemplate">
  <StackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>

Вот xamlдля ItemTemplate - обратите внимание, что я привязываюсь к WidthOfPlay, так как один ярд составляет примерно 6 единиц на фоновом изображении, как только я разберу рисунок и изменение размера, я свяжусь с фактическим свойством Result:

<DataTemplate x:Key="myDataTemplate">
  <StackPanel Orientation="Horizontal" Width="{Binding WidthOfPlay}"
              SnapsToDevicePixels="True" Style="{StaticResource onMouseOver}">
    <Border Padding="0,5,0,5">
      <Grid>
        <StackPanel Style="{StaticResource onMouseOver}">
          <Rectangle Width="{Binding WidthOfPlay}" Height="10" 
                     Fill="{Binding TypeOfPlay,
                       Converter={StaticResource PlayTypeToColourConverter}}" />
        </StackPanel>
      </Grid>
    </Border>
  </StackPanel>
</DataTemplate>

Я конвертирую перечисление PlayType в Brush, поэтому с примерами данных вы можете видеть отображаемые цвета.

<converter:PlayToColour x:Key="PlayTypeToColourConverter"
  ColourRun="Red" ColourPass="Blue" ColourPenalty="Yellow" ColourSpecial="Purple" />

Так что все работает нормально - но, очевидно, представлениене так, как хотелось бы - если посмотреть на пример сверху, диск состоит из множества пьес, которые расположены рядом друг с другом, но так как игра может привести к отрицательному методу, они также размещаются друг под другом, смещенные на конецпоследняя игра!

Так что, я думаю, это мой вопрос - как я могу представить данные в такой форме, чтобы каждая игра на диске располагалась под предыдущей игрой на этом диске, но также начиналась сконец этого последнего диска (как-то смещен?)

Поскольку игра состоит из более чем одного диска, на более позднем этапе я буду передавать список «Дисков», состоящий из начальной позиции диска исписок игр для этого диска (вместо простого списка игр в этом примере).

Это означает, что ктоВсе должно быть прокручиваемым !

Я думаю, что я на правильном пути, используя элемент управления ItemsControl вместе с ItemTemplate и DataTemplate, но я мог бы наверняка использовать некоторые советы экспертов, како том, как этого добиться.

Если вы читали это далеко, спасибо за ваше время - GO PATS;)

[править]

Хорошо благодаря AngelWPF (virtualization) и Rachel (все!) Мне действительно удалось заставить его работать, по крайней мере для списка игр, которыми я предоставлял ItemsControl.Рейчел, у тебя отличный блог.Запись AttachedProperties действительно была очень полезна, спасибо, что поделились своими знаниями!

На более позднем этапе я надеюсь, что смогу добавить один или два снимка экрана, которые лучше демонстрируют то, о чем я болтаю;)

Как было предложено, я изменил класс Play с помощью (среди прочих свойств) PlayIndex для позиционирования сетки

public class Play
{
  public int PlayIndex { get; set; }
  public int Quarter { get; set; }
  public int Down { get; set; }
  public int YardsToGo { get; set; }
  public int Position { get; set; }
  public PlayType TypeOfPlay { get; set; }
  public PlayDetail DetailsOfPlay { get; set; }
  public PlayResult ResultOfPlay { get; set; }
  public int YardsOfPlay { get; set; }
  public double PlayLength { get; set; }
  public string Player1 { get; set; }
  public string Player2 { get; set; }
}

и для использования этого PlayIndex ItemContainerStyle был добавлен в ItemsControl

<ItemsControl.ItemContainerStyle>
  <Style>
    <Setter Property="Grid.Column" Value="{Binding PlayIndex}" />
    <Setter Property="Grid.Row" Value="{Binding PlayIndex}" />
  </Style>
</ItemsControl.ItemContainerStyle>

Помогло и изменение ItemsPanelTemplate со StackPanel на Grid :) Теперь каждая игра отображается рядом друг с другом, а также под другим цветом.Добавление всплывающей подсказки к ItemsControl (с использованием других свойств в классе Play) отполировало его.

Как я уже говорил, теперь это прекрасно работает со списком элементов Play (сокращено для простоты):

List<Play> SamplePlays = new List<Play>()
{
  new Play { PlayIndex = 0, Position = 30, YardsOfPlay = 5, PlayLength = 25 },
  new Play { PlayIndex = 1, Position = 35, YardsOfPlay = 15, PlayLength = 75 },
  new Play { PlayIndex = 2, Position = 50, YardsOfPlay = 0, PlayLength = 0 },
  new Play { PlayIndex = 3, Position = 50,  YardsOfPlay = 8, PlayLength = 40 },
  new Play { PlayIndex = 4, Position = 58,  YardsOfPlay = 1, PlayLength = 5 },
  new Play { PlayIndex = 5, Position = 59,  YardsOfPlay = 30, PlayLength = 150 }
};

Но как мне связать то, что я написал в конце исходного поста, относительно передачи списка «Дисков»?

Пожалуйстаобратите внимание - со мной, написав это в оригинальном сообщении, я надеюсь, что это «позволяет» мне редактировать этот пост с дополнительной информацией и не задавать совершенно новый вопрос!

Учитывая следующееКласс «Drive»:

public class Drive
{
  public int DriveIndex { get; set; }
  public int StartPos { get; set; }
  public int EndPos { get; set; }
  public double DriveLength { get; set; }
  public DriveResult Result { get; set; }
  public List<Play> DrivePlays { get; set; }
}

Заполнение списка данными (с использованием тех же игр, что и выше)

List<Drive> SampleDrives = new List<Drive>() 
{
  new Drive { DriveIndex = 0, StartPos = 30, EndPos = 49, DriveLength = 19,
              DrivePlays = new List<Play>() 
              {
                // create plays here
              }},
  new Drive { DriveIndex = 1, StartPos = 30, EndPos = 49, DriveLength = 19,
              DrivePlays = new List<Play>() 
              {
                // create plays here
              }}
};

и ViewModel теперь выглядит так:

public class ucDriveChartVM : ViewModelBase
{
  public List<Play> DriveDetails { get; set; }
  public List<Drive> Drives { get; set; }

  public ucDriveChartVM(ucDriveChartTP transferParameter)
  {
    this.DriveDetails = transferParameter.Plays;
    this.Drives = transferParameter.Drives;
  }
}

Мне, очевидно, нужно предоставить этому ItemsControl (содержащему диски) другой DataTemplate, но этот DataTemplate должен был бы содержать воспроизведения в этом списке дисков.Я быстро обнаружил, что вы не можете поместить контент в прямоугольник, поэтому мне нужно подумать об этом: /

После небольшого эксперимента я привязался к свойству DriveLength, чтобы графически увидеть длинуданный диск и придумал DataGridCell, чтобы я мог поместить туда контент (например, StackPanel).

(я знаю, что не привязан ни к чему, кроме длины диска, прямоугольника вэтот пример просто показывает что-то, когда я тестирую!)

<DataTemplate x:Key="myDataTemplateDrives">
  <StackPanel Orientation="Horizontal" Width="{Binding DriveLength}" 
              SnapsToDevicePixels="True" Margin="0,0,1,0">
    <Border>
      <Grid>
        <StackPanel>
          <DataGridCell>
            <StackPanel Width="{Binding Path=DriveLength}">
              <Rectangle Height="10" Fill="Gray" />
            </StackPanel>
          </DataGridCell>
        </StackPanel>
      </Grid>
    </Border>
  </StackPanel>
</DataTemplate>

Но я уже прошел четвертую чашку кофе, и у меня возникли проблемы с привязкой к списку внутри объекта List?Что-то вроде Drives.DrivePlays?!

Итак, я иду от простого (спасибо вам обоим)

List<Play>

к привязке

List<Drive>

,который содержит

List<Play>!

, называемый «DrivePlays»: D

Я что-то упускаю из виду или мне нужно больше кофе?

edit

Я объяснил последнюю часть проблемы в отдельном вопросе

Смежный вопрос относительно последней части исходного вопроса

Ответы [ 2 ]

0 голосов
/ 11 октября 2011

Позвольте мне начать с того, что я ничего не знаю о футболе, поэтому, если я вас правильно понял, простите меня.

Начнем с того, что ItemsControl фактически оборачивает каждый элемент в ContentPresenter, поэтому он не будет работать, чтобы отрегулировать позиционирование ваших элементов от вашего DataTemplate. Если вы хотите изменить расположение ваших предметов, вам нужно использовать ItemContainerStyle (например, см. здесь )

Из-за того, как вы хотите расположить свои данные, я хотел бы попытаться добавить свойства Grid.Row / Grid.Column к вашему классу Play и выяснить, какими они должны быть в коде. Затем вы можете нарисовать ваш ItemsControl в виде таблицы со столбцами / строками на основе количества строк / столбцов в списке Plays и поместить каждый элемент в соответствующую ячейку. (У меня есть пример использования Attached Properties для определения Grid.Rows / Columns здесь , хотя я считаю, что им нужны некоторые незначительные изменения для привязки значений ... нужно изменить Grid на GridHelpers и изменить Register на RegisterAttached)

Для прокрутки ItemsControl вы можете обернуть его в ScrollViewer. Если вы также хотите виртуализировать ItemsControl, проверьте этот вопрос

0 голосов
/ 11 октября 2011

Я предлагаю для выравнивания макета элементов данных и их виртуализации проанализировать строгие параметры, предоставляемые всеми элементами управления элементами в WPF ...

  1. ItemsControl с UniformGrid как ItemsPanel.
  2. ListBox с прозрачной кистью выделения (чтобы она выглядела как элемент управления) обеспечивает встроенную виртуализацию.
  3. ListView обеспечивает макет выравнивания GridView и виртуализацию.
  4. WPF DataGrid может использоваться для лучших параметров, таких как виртуализация столбцов / строк, сортировка и т. Д. *
  5. Однако вы можете реализовать виртуализованный ItemsControl в версии до 4.0, http://omniscientist.net:8081/efficientlargedatasets
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...