Zaryab Waseem
Zaryab Waseem

Reputation: 156

How to make a StackPanel visible only when the DragCompleted + Condition is matched

I am working on a UWP app in which my requirement is to show a StackPanel only when Drag is completed in a grid view and condition is met too.
I am making a drag and re-order like game. I want the StackPanel (Containing Result and Buttons) appear when not only a single drag is completed but all the items are sorted too.
I have got everything else working fine. Only StackPanel is problem. It appears just after on drag completed whether the condition is met or not.
Following are the screenshots, code and more briefing !

ScreenShot When game starts, Grid Items are Un-ordered. Game ends when they are ordered.

Stack Panel to show result

XAML for GridView

<GridView Name="GameDisplay"
                      HorizontalAlignment="Center"
                      VerticalAlignment="Center"
                      Grid.Row="1"
                      Grid.Column="1"
                      CanDrag="True"
                      CanDragItems="True"
                      CanReorderItems="True"
                      SelectionMode="Single"
                      AllowDrop="True"
                      DragItemsCompleted="GameDisplay_DragItemsCompleted">
            <GridView.ItemTemplate>
                <DataTemplate>
                    <Grid Width="60" 
                              Height="60"
                              Background="Black">
                        <TextBlock Text="{Binding}"
                                       FontFamily="BriLliant" 
                                       FontSize="48" 
                                       FontWeight="light" 
                                       Foreground="White"
                                       TextAlignment="Center"
                                       HorizontalAlignment="Center"
                                       VerticalAlignment="Center"/>
                    </Grid>

                </DataTemplate>
            </GridView.ItemTemplate>
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <ItemsWrapGrid Orientation="Horizontal"
                                   MaximumRowsOrColumns="10"/>
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
        </GridView>

XAML For StackPanel

        <StackPanel Grid.Row="1" Grid.Column="1" Name="GameFinished" Background="#9900ff" Width="800" HorizontalAlignment="Center" VerticalAlignment="Center" Height="auto">
            <Grid Name="InnerGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="4*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <StackPanel Name="BtnsContainer" Grid.Column="1" Width="auto" Height="auto" Margin="0 10 0 0">
                    <Grid Name="BtnsGrid">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <TextBlock Name="txtBannerType"
                                   Width="auto"
                                   Height="auto"
                                   Grid.Row="0"
                                   Text="Well Done !"
                                   FontSize="72" 
                                    FontWeight="Bold" 
                                    FontFamily="BriLliant" 
                                    Foreground="White"
                                   TextAlignment="Center"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"/>
                        <TextBlock Name="txtTimeSpent"
                                   Width="200"
                                   Height="auto"
                                   Grid.Row="1"
                                   Text=""
                                   FontSize="48" 
                                    FontWeight="Light" 
                                    FontFamily="BriLliant" 
                                    Foreground="White"
                                   TextAlignment="Center"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"/>
                        <TextBlock Name="txtScore"
                                   Width="200"
                                   Height="auto"
                                   Grid.Row="2"
                                   Text="Score : 0"
                                   FontSize="48" 
                                    FontWeight="Light" 
                                    FontFamily="BriLliant" 
                                    Foreground="White"
                                   TextAlignment="Center"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"/>
                        <TextBlock Name="txtBestScore"
                                   Width="200"
                                   Height="auto"
                                   Grid.Row="3"
                                   Text="Best Score : 0"
                                   FontSize="48" 
                                    FontWeight="Light" 
                                    FontFamily="BriLliant" 
                                    Foreground="White"
                                   TextAlignment="Center"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"/>
                        <Button Name="RestartGame" 
                                Width="200" 
                                Height="70" 
                                Grid.Row="4" 
                                Background="Black" 
                                Content="Restart" 
                                FontSize="48" 
                                FontWeight="Bold" 
                                FontFamily="BriLliant" 
                                Foreground="White" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center" 
                                Margin="0 20 0 0"
                                Click="RestartGame_Click"/>
                        <Button Name="MainMenu" 
                                Width="200" 
                                Height="70" 
                                Grid.Row="5" 
                                Background="Black" 
                                Content="Main Menu" 
                                FontSize="48" 
                                FontWeight="Bold" 
                                FontFamily="BriLliant" 
                                Foreground="White" 
                                HorizontalAlignment="Center" 
                                VerticalAlignment="Center" 
                                Margin="0 20 0 0"
                                Click="MainMenu_Click"/>

                    </Grid>
                </StackPanel>
</Grid>
        </StackPanel>

C# Events

 private void Page_Loaded(object sender, RoutedEventArgs e)
            {
            lib.New(GameDisplay);//For Starting New Game
            }

private void GameDisplay_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
            {

            lib.completed(GameDisplay);//When the tiles are re-ordered
            }

Class that is handling BackEnd

class Library
    {
    //BackEnd for Math Game
    private const int size = 5;
    private const int total = size * size;
    private DateTime timer;
    private ObservableCollection<int> items = new ObservableCollection<int>();
    private Random random = new Random((int)DateTime.Now.Ticks);
    public void show(string content, string title)
        {
        IAsyncOperation<IUICommand> command = new MessageDialog(content, title).ShowAsync();
        }
    private List<int> select(int start, int finish, int total)
        {
        int number;
        List<int> numbers = new List<int>();
        while ((numbers.Count < total))
            {
            number = random.Next(start, finish + 1);
            if ((!numbers.Contains(number)) || (numbers.Count < 1))
                {
                numbers.Add(number);
                }

            }
        return numbers;
        }
    private bool winner()
        {
        return items.OrderBy(o => o).ToList().SequenceEqual(items.ToList());
        }
    private void layout(ref GridView grid)
        {
        timer = DateTime.UtcNow;
        grid.IsEnabled = true;
        grid.ItemsSource = null;
        items = new ObservableCollection<int>();
        List<int> numbers = select(1, total, total);
        int index = 0;
        while (index < numbers.Count)
            {
            items.Add(numbers[index]);
            index++;
            }
        grid.ItemsSource = items;
        }
    public void New(GridView grid)
        {
        layout(ref grid);
        }
    public void completed(GridView grid)
        {
        string congo = "";
        if (winner())
            {
            TimeSpan duration = (DateTime.UtcNow - timer).Duration();
            congo = string.Format("Time: {0}:{1}:{2}", duration.Hours, duration.Minutes, duration.Seconds);
            grid.IsEnabled = false;

            }

        }

    }

Above is the game screen. When I drag and re-order a tile an event is fired in which a method runs until all the tiles are dragged and reordered according to the index of list that is containing all these numbers.
StackPanel only waits for one Drag. Is there any way to add StackPanel into the condition that checks for list sort?? Something like Data-Binding?? If you find anything missing, wrong or the question is already solved before. Please let me know explicitly ! Thanks...

Upvotes: 0

Views: 736

Answers (3)

Sunteen Wu
Sunteen Wu

Reputation: 10627

Since you have already use winner() method to judge whether the game is ended and also invoke this in GameDisplay_DragItemsCompleted method. So actually the condition is already met in your completed method (every drag completed to judge whether game is over ). We just need to set the Visibility property of StackPanel to visible.

Update complete method as follows:

public void completed(GridView grid,StackPanel stackpanel)
{
    string congo = "";
    if (winner())
    {
        TimeSpan duration = (DateTime.UtcNow - timer).Duration();
        congo = string.Format("Time: {0}:{1}:{2}", duration.Hours, duration.Minutes, duration.Seconds);
        grid.IsEnabled = false;
        stackpanel.Visibility = Visibility.Visible;
    }
}

Update GameDisplay_DragItemsCompleted method as follows:

private void GameDisplay_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
    lib.completed(GameDisplay,GameFinished);//When the tiles are re-ordered
}

Pay attention that in default the StackPanel should be collapsed. Update XAML code about StackPanel as follows:

 <StackPanel Grid.Row="1" Grid.Column="1" Name="GameFinished" Background="#9900ff" Width="800" HorizontalAlignment="Center" VerticalAlignment="Center" Height="auto" Visibility="Collapsed">

And you can reset the state for StackPanel and GridView when game restart. Code as follows:

 private void RestartGame_Click(object sender, RoutedEventArgs e)
 {
     GameDisplay.IsEnabled = true;
     GameFinished.Visibility = Visibility.Collapsed;
 }

And the result:

enter image description here

Upvotes: 1

Jet  Chopper
Jet Chopper

Reputation: 1488

You may create two bool flags and check them in both methods OnDragComplete and OnChangeCondition like this:

    private void OnDragComplete()
    {
        _isDragCompleted = true;
        if (_isDragCompleted && _isConditionChanged)
        {
            CollapseStackPanel();
        }
    }

    private void OnChangeCondition()
    {
        _isConditionChanged = true;
        if (_isDragCompleted && _isConditionChanged)
        {
            CollapseStackPanel();
        }
    }

    private void CollapseStackPanel()
    {
        _isDragCompleted = false;
        _isConditionChanged = false;
        StackPanel.Visibility = Visibility.Collapsed;
    }

Upvotes: 1

t.m.
t.m.

Reputation: 1490

The problem is, by this code in winner function

return items.OrderBy(o => o).ToList().SequenceEqual(items.ToList()); }

You just check if list items is equal to list items. It will always return true. According to this msdn document orderBy orders the list itself does not return a copy of it.

If you are going to use this method, create another list to compare with curent list and keep that list sorted.

Upvotes: 1

Related Questions