Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>As OJ suggested, you should use data binding. This lets you separate the problem of presenting the game on the screen from the problem of managing the game's internal logic.</p> <p>You'll need to create a <code>Cell</code> class that exposes <code>Row</code>, <code>Column</code>, and <code>Owner</code> properties. The class will need to implement <code>INotifyPropertyChanged</code> so that when the <code>Owner</code> gets changed, it can alert the UI by raising the <code>PropertyChanged</code> event. Finally, the class will implement a <code>SelectCellCommand</code>, which will set the <code>Owner</code> for the cell appropriately when it's executed (and whose <code>CanExecute</code> property will be set to false once the cell's owner has been set).</p> <p>You'll create a collection that contains nine of these <code>Cell</code>s, with <code>Row</code>, <code>Column</code>, and <code>Owner</code> properties set to the appropriate initial values. All of your game logic (e.g. who's turn is it? Has someone won?) will examine this collection.</p> <p>In the UI, you'll create an <code>ItemsControl</code> that's bound to the collection of <code>Cell</code>s. Each item in the control will be a cell in the grid. </p> <p>You'll set the <code>ItemsPanel</code> to a <code>Grid</code>, which will tell the <code>ItemsControl</code> how to lay its items out. You'll create an <code>ItemContainerStyle</code> that assigns the <code>Grid.Row</code> and <code>Grid.Column</code> attached properties to the items' containers - the <code>ItemsControl</code> creates an <code>ItemsPresenter</code> for each object in the <code>ItemsSource</code>, and the <code>Grid.Row</code> and <code>Grid.Column</code> properties must be set on this object in order for the <code>Grid</code> to see them and know where to put them. </p> <p>Finally, the control will contain an <code>ItemTemplate</code> that describes how each item should be displayed. I'm using a <code>Button</code> (since you want there to be a command that executes when the user clicks on it) that contains a <code>TextBlock</code> which displays the X or the O in <code>Owner</code>.</p> <p>It might look something like this:</p> <pre><code>&lt;ItemsControl ItemsSource="{Binding {StaticResource Cells}}"&gt; &lt;ItemsControl.ItemsPanel&gt; &lt;ItemsPanelTemplate&gt; &lt;Grid&gt; &lt;Grid.ColumnDefinitions&gt; &lt;ColumnDefinition/&gt; &lt;ColumnDefinition/&gt; &lt;ColumnDefinition/&gt; &lt;/Grid.ColumnDefinitions&gt; &lt;Grid.RowDefinitions&gt; &lt;RowDefinition/&gt; &lt;RowDefinition/&gt; &lt;RowDefinition/&gt; &lt;/Grid.RowDefinitions&gt; &lt;/Grid&gt; &lt;/ItemsPanelTemplate&gt; &lt;ItemsPanel.ItemContainerStyle&gt; &lt;Style TargetType="ItemPresenter"&gt; &lt;Setter Property="Grid.Column" Value="{Binding Column}"/&gt; &lt;Setter Property="Grid.Row" Value="{Binding Row}"/&gt; &lt;/Style&gt; &lt;/ItemsPanel.ItemContainerStyle&gt; &lt;ItemsPanel.ItemTemplate&gt; &lt;DataTemplate DataType="local:Cell"&gt; &lt;Button Command="{Binding SelectCellCommand}" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"&gt; &lt;TextBlock FontSize="72" Source="{Binding Owner}"/&gt; &lt;/Button&gt; &lt;/DataTemplate&gt; &lt;/ItemsPanel.ItemTemplate&gt; &lt;/ItemsControl&gt; &lt;/ItemsControl&gt; </code></pre> <p>Why go through all of this?</p> <p>Well, let's look at the problems that your current design has that this doesn't:</p> <ol> <li><p>If you want to change the layout of the cells in your design, you have nine different controls you need to fix. Here, you just change the <code>DataTemplate</code> for the cells.</p></li> <li><p>There's no need for nine different event handlers. Because the buttons are bound to command objects that are properties of the <code>Cell</code>, you don't need to implement any way of finding out which cell the user just clicked on - the command <em>is</em> the way. Also, you can disable the command (and its button) very simply once the <code>Owner</code> is set.</p></li> <li><p>All of your game logic can look at a simple data structure - a collection of <code>Cell</code> objects - without being concerned about how the UI works.</p></li> </ol> <p>Finally, and most important, data binding is the core of WPF application development. It's what makes developing WPF applications far easier than it was to implement WinForms applications. If you're learning WPF without learning binding, you're wasting time.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload