Использование StyleSelector в UWP для изменения стилей ListViewItem для игры Minesweeper - PullRequest
0 голосов
/ 27 апреля 2018

Я делаю клон тральщика для класса. Основная игровая доска генерируется с помощью кода, но это серия ListView столбцов, содержащих ряды Tile объектов. Этот код генерирует ListViews (работает нормально):

  // Create as many lists as necessary to fill the board according to the size specified
  void createGameBoard(bool erase = true)
  {
     // Erase any previous game
     if(erase)
     {
        for(int i = mainGameBoard.Children.Count; i > 0; i--)
        {
           mainGameBoard.Children.RemoveAt(i - 1);
        }
     }

     //        Main Game Board
     // column 0   column 1   column 2
     // tile 0,0   tile 1,0   tile 2,0
     // tile 0,1   tile 1,1   tile 2,1
     // tile 0,2   tile 1,2   tile 2,2
     // Create a new list view for each game board column
     for(uint col = 0; col < minesweepGame.Width; col++)
     {
        ListView column = new ListView();
        column.Name = col.ToString();
        column.SelectionMode = ListViewSelectionMode.None;
        column.IsItemClickEnabled = true;
        column.ItemClick += Column_ItemClick;
        ///column.ItemContainerStyleSelector.SelectStyle()

        // Fill the column with tiles
        Tile[] columnTiles = new Tile[minesweepGame.Width];
        for(uint row = 0; row < minesweepGame.Width; row++)
        {
           columnTiles[row] = minesweepGame.TileList[col, row];
        }
        column.ItemsSource = columnTiles;

        // Append the newly created column to the main game board (in order of creation)
        mainGameBoard.Children.Add(column);
     }
  }

В результате получается чистая сетка с анимацией.

UWP Сапер, использующий ListViews

Я хочу по-разному оформлять элементы, когда они открываются пользователю (при нажатии на них тайл становится темнее и имеет номера с разными цветами). Поэтому я просмотрел документацию и примеры и создал StyleSelector:

   public class ColumnTileSelector : StyleSelector
   {
      private Style Tile0 = new Style(typeof(ListViewItem));
      private Style Tile1 = new Style(typeof(ListViewItem));
      private Style Tile2 = new Style(typeof(ListViewItem));
      private Style Tile3 = new Style(typeof(ListViewItem));
      private Style Tile4 = new Style(typeof(ListViewItem));

      protected override Style SelectStyleCore(object item, DependencyObject container)
      {
         Tile tile = (Tile)item;
         if(tile.IsShownGraphically)
         {
            switch(tile.AdjacentMines)
            {
               case 0:
                  Tile0.Setters.Add(new Setter(Control.BackgroundProperty, Colors.Red));
                  return Tile0;
               case 1:
                  return Tile1;
               case 2:
                  return Tile2;
               case 3:
                  return Tile3;
               case 4:
                  return Tile4;
               default:
                  return Tile0;
            }
         }
         else
         {
            return Tile0;
         }
      }
   }

У меня также были ранее созданные стили в XAML:

   <!-- style the game grid tiles -->
   <Page.Resources>
      <Style TargetType="ListViewItem">
         <Setter Property="MinWidth" Value="30"/>
         <Setter Property="MinHeight" Value="30"/>
         <Setter Property="MaxWidth" Value="30"/>
         <Setter Property="MaxHeight" Value="30"/>
         <Setter Property="Padding" Value="2, 2, 2, 2"/>
         <Setter Property="BorderBrush" Value="SlateGray"/>
         <Setter Property="BorderThickness" Value="1"/>
         <Setter Property="HorizontalContentAlignment" Value="Center"/>
         <Setter Property="FontWeight" Value="ExtraBlack"/>
         <Setter Property="Foreground" Value="DarkBlue"/>
      </Style>

      <Style TargetType="ListViewItem" x:Key="Tile0">
         <Setter Property="Background" Value="LightGray"/>
         <Setter Property="Foreground" Value="Transparent"/>
      </Style>

      <Style TargetType="ListViewItem" x:Key="Tile1">
         <Setter Property="Background" Value="LightGray"/>
         <Setter Property="Foreground" Value="DarkBlue"/>
      </Style>

      <Style TargetType="ListViewItem" x:Key="Tile2">
         <Setter Property="Background" Value="LightGray"/>
         <Setter Property="Foreground" Value="Green"/>
      </Style>

      <Style TargetType="ListViewItem" x:Key="Tile3">
         <Setter Property="Background" Value="LightGray"/>
         <Setter Property="Foreground" Value="Red"/>
      </Style>

      <Style TargetType="ListViewItem" x:Key="Tile4">
         <Setter Property="Background" Value="LightGray"/>
         <Setter Property="Foreground" Value="DarkOrange"/>
      </Style>

      <Style TargetType="StackPanel" x:Key="mainGameBoard">
         <Setter Property="BorderBrush" Value="SlateGray"/>
         <Setter Property="BorderThickness" Value="0"/>
      </Style>

      <local:ColumnTileSelector x:Key="tileColor"/>
   </Page.Resources>

Однако на самом деле ничего не работает.

  1. Как мне обратиться к стилям из XAML в коде представления?
  2. Что более важно, как мне указать, что мой ListViews должен использовать ColumnTileSelector?
  3. В коде, который генерирует ListViews, я закомментировал ///column.ItemContainerStyleSelector.SelectStyle(). Можно ли здесь указать мой класс ColumnTileSelector? Я в замешательстве.

В документации неясно, как вещи связаны друг с другом. Я понимаю в принципе, но ни один из примеров, которые я вижу, не указывает, почему вещи реагируют так, как они.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018
  1. Для обращения к стилю в коде представления требуется пара шагов. Во-первых, создайте переменную типа страницы в представлении: static MainPage mainPage; Во-вторых, инициализируйте ее в конструкторе страницы: mainPage = this; В-третьих, используйте стиль в контроллере представления: mainPage.Resources["TileExploded"] as Style;

  2. Чтобы указать, какое StyleSelector представление списка должно использовать программно, используйте этот код: column.ItemContainerStyleSelector = new ColumnStyleSelector();, где column - это ListView.

В результате можно отобразить элементы ListViewItem с разными стилями, используя логику в StyleSelector:

  // Selects what style applies to a list view item according to that item's properties when it is rendered
  public class ColumnStyleSelector : StyleSelector
  {
     protected override Style SelectStyleCore(object item, DependencyObject container)
     {
        Tile tile = (Tile)item;

        if(tile.Type == (int)TileType.ExplodedMine)
        {
           return mainPage.Resources["TileExploded"] as Style;
        }
        else if(tile.IsRevealed == true && tile.IsShownGraphically == true)
        {
           switch(tile.AdjacentMines)
           {
              case 0:
                 return mainPage.Resources["Tile0"] as Style;
              case 1:
                 return mainPage.Resources["Tile1"] as Style;
              case 2:
                 return mainPage.Resources["Tile2"] as Style;
              case 3:
                 return mainPage.Resources["Tile3"] as Style;
              case 4:
                 return mainPage.Resources["Tile4"] as Style;
              default:
                 return mainPage.Resources["ListViewItem"] as Style;
           }
        }
        else
        {
           return mainPage.Resources["ListViewItem"] as Style;
        }
     }
  }

Это, конечно, может использовать любую логику, специфичную для программы, с ключевыми утверждениями return mainPage.Resources["XAML Resource Style Key Here"] as Style;

0 голосов
/ 27 апреля 2018
<Page>
    <Page.Resources>
         <Style TargetType="ListViewItem" x:Key="Tile1">
              <Setter Property="Background" Value="LightGray"/>
              <Setter Property="Foreground" Value="DarkBlue"/>
         </Style>
         <support:ColumnStyleSelector x:Key="ColumnStyleSelector"    
              Tile1="{StaticResource Tile1}"/>
    </Page.Resources>
   <Grid>
    <ListView ItemContainerStyleSelector="{StaticResource ColumnStyleSelector}"/>
</Page>
  1. Сделать стили Tile1, Tile2 и т. Д. Общедоступными свойствами ColumnStyleSelector
  2. Поместите стили на странице Ресурсы
  3. Поместите ColumnStyleSelector на странице Ресурсы
  4. Ссылка на стили в ресурсах в атрибутах ColumnStyleSelector
...