Reputation: 1079
I have created a simple Tic Tac Toe application to learn WPF. But I can't manage to bind the o_win_counter to my o_win_count label. How to achieve this? Later on I also want to bind the other counter labels to variables.
App.xaml
<Application x:Class="FirstApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary Source="ResourceDictionary.xaml" />
</Application.Resources>
ResourceDictionary.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="#FF959595" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="10,0" />
<Setter Property="Margin" Value="2" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="Height" Value="25" />
<Setter Property="MinWidth" Value="100" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ColorAnimation To="#FFFFFFFF" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Duration="0:0:0.07" />
<ColorAnimation To="#FFDEDEDE" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Duration="0:0:0.07" />
<ColorAnimation To="#FF959595" Storyboard.TargetName="BrBrush"
Storyboard.TargetProperty="Color" Duration="0:0:0.07" />
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation To="#FF00B4E4" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Duration="0:0:0.07" />
<ColorAnimation To="#FF0083C3" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Duration="0:0:0.07" />
<ColorAnimation To="#FF4C7B8F" Storyboard.TargetName="BrBrush"
Storyboard.TargetProperty="Color" Duration="0:0:0.07" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation To="#DBEDFD" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Duration="0:0:0.05" />
<ColorAnimation To="#C4E0FC" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Duration="0:0:0.05" />
<ColorAnimation To="#4C7B8F" Storyboard.TargetName="BrBrush"
Storyboard.TargetProperty="Color" Duration="0:0:0.05" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation To="#EB2828" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Duration="0:0:0" />
<ColorAnimation To="#EB2828" Storyboard.TargetName="BgBrush"
Storyboard.TargetProperty="(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Duration="0:0:0" />
<ColorAnimation To="#D9D9D9" Storyboard.TargetName="BrBrush"
Storyboard.TargetProperty="Color" Duration="0:0:0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Chrome" BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<Border.BorderBrush>
<SolidColorBrush x:Name="BrBrush" Color="#ACACAC" />
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush x:Name="BgBrush" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0" />
<GradientStop Color="#FFE5E5E5" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#FFFFFF" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Foreground" Value="#000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FirstApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public bool turn = true;
public int turn_count = 0;
private int _o_win_counter;
public MainWindow()
{
InitializeComponent();
}
public int o_win_counter
{
get
{
return _o_win_counter;
}
set
{
if (_o_win_counter != value)
{
_o_win_counter = value;
OnPropertyChanged("o_win_counter");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void button_click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
if (turn)
button.Content = "X";
else
{
button.Content = "O";
}
turn = !turn;
button.IsEnabled = false;
turn_count++;
checkForWinner();
}
private void checkForWinner()
{
bool isWinner = false;
//horizontal
if (A.Content == B.Content && (B.Content == C.Content) && (!A.IsEnabled))
isWinner = true;
else if (D.Content == E.Content && (D.Content == F.Content) && (!D.IsEnabled))
isWinner = true;
else if (G.Content == H.Content && (G.Content == I.Content) && (!G.IsEnabled))
isWinner = true;
//vertical
else if (A.Content == D.Content && (D.Content == G.Content) && (!A.IsEnabled))
isWinner = true;
else if (B.Content == E.Content && (B.Content == H.Content) && (!B.IsEnabled))
isWinner = true;
else if (C.Content == F.Content && (C.Content == I.Content) && (!C.IsEnabled))
isWinner = true;
//diagonal
else if (A.Content == E.Content && (E.Content == I.Content) && (!A.IsEnabled))
isWinner = true;
else if (G.Content == E.Content && (E.Content == C.Content) && (!G.IsEnabled))
isWinner = true;
if (isWinner)
{
disableButtons();
String winner = "";
if (turn)
{
winner = "O";
}
else
{
winner = "X";
o_win_counter++;
}
MessageBox.Show(winner + " Wins!", "Winner");
}
else
{
if(turn_count==9)
MessageBox.Show("Draw", "Draw!");
}
}
private void disableButtons()
{
try
{
foreach (Control control in controlGrid.Children)
{
if (control is Button)
{
Button button = (Button)control;
button.IsEnabled = false;
}
}
}
catch { }
}
private void newButton_Click(object sender, RoutedEventArgs e)
{
turn = true;
turn_count = 0;
try
{
foreach (Control control in controlGrid.Children)
{
if (control is Button)
{
Button button = (Button)control;
button.IsEnabled = true;
button.Content = "";
}
}
}
catch { }
}
private void button_enter(object sender, MouseEventArgs e)
{
Button button = (Button)sender;
if (button.IsEnabled)
{
if (turn)
button.Content = "X";
else
button.Content = "O";
}
}
private void button_leave(object sender, MouseEventArgs e)
{
Button button = (Button)sender;
if (button.IsEnabled)
button.Content = "";
}
}
}
MainWindow.xaml
<Window x:Class="FirstApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="525" Name="MyWindow">
<Grid Margin="0,0,0.4,-19.2" Name="controlGrid">
<Button x:Name="A" Content="" HorizontalAlignment="Left" Margin="117,59,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="B" Content="" HorizontalAlignment="Left" Margin="223,59,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="C" Content="" HorizontalAlignment="Left" Margin="330,59,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="D" Content="" HorizontalAlignment="Left" Margin="117,157,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="E" Content="" HorizontalAlignment="Left" Margin="223,157,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="F" Content="" HorizontalAlignment="Left" Margin="330,157,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="G" Content="" HorizontalAlignment="Left" Margin="117,255,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="H" Content="" HorizontalAlignment="Left" Margin="223,255,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<Button x:Name="I" Content="" HorizontalAlignment="Left" Margin="330,255,0,0" VerticalAlignment="Top" Width="75" Height="75" Click="button_click" Background="#FFEBEB33" MouseEnter="button_enter" MouseLeave="button_leave" FontSize="36"/>
<ToolBar Margin="0,0,0,450.6">
<Button Name="newButton" Click="newButton_Click">New</Button>
</ToolBar>
<Label Content="X Win Count" HorizontalAlignment="Left" Margin="117,369,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<Label Content="Draw Count" HorizontalAlignment="Left" Margin="233,369,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<Label Content="O Win Count" HorizontalAlignment="Left" Margin="348,369,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<Label x:Name="x_win_count" Content="0" HorizontalAlignment="Left" Margin="138,400,0,0" VerticalAlignment="Top"/>
<Label x:Name="draw_count" Content="0" HorizontalAlignment="Left" Margin="259,400,0,0" VerticalAlignment="Top"/>
<Label x:Name="o_win_count" Content="{Binding Path=_o_win_counter, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="381,400,0,0" VerticalAlignment="Top"/>
</Grid>
Upvotes: 1
Views: 12353
Reputation: 128146
Replace
Content="{Binding Path=_o_win_counter, ...}"
with
Content="{Binding Path=o_win_counter, ...}"
without the leading underline. The binding source must be the property, not the backing field. You may also rethink your property names. There is a widely accepted convention that property names in C# use CamelCasing.
Then you also have to specify the source object of the binding, which is the MainWindow instance in this case. There are a few ways to do this, but the perhaps simplest way here is to set the Window's DataContext property:
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
You might want to read the Data Binding Overview article on MSDN.
Upvotes: 6
Reputation: 1327
You should set your datacontext in constructor:
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
You don't use MVVM so why don't you set it from code behind like:
o_win_count.Content= o_win_counter.ToString();
Upvotes: 0