0

I'm making a bingo card generator to try and learn more about WPF, and having trouble figuring out how to set a labels content property to be set from a Property in my code-behind file.

I thought that I could use

<Setter Property="Content" Value="{Binding BNumber}">

for the content property to set the content of the label to a random element of my List<String>?

I have in my MainWindow.xaml

<Window x:Class="Bingo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="600" Width="800"
        WindowStartupLocation="CenterScreen">
  <Grid>
    <Grid Width="350" Height="420" ShowGridLines="True">
      <Grid.RowDefinitions>
        <RowDefinition Height="70"/>
        <RowDefinition Height="70"/>
        <RowDefinition Height="70"/>
        <RowDefinition Height="70"/>
        <RowDefinition Height="70"/>
        <RowDefinition Height="70"/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="70" />
        <ColumnDefinition Width="70" />
        <ColumnDefinition Width="70" />
        <ColumnDefinition Width="70" />
        <ColumnDefinition Width="70" />
      </Grid.ColumnDefinitions>
      <!-- The Label I'm trying to set in this example -->
      <Label Grid.Column="0" Grid.Row="1" Style="{StaticResource BNumber}"
             FontSize="50" Width="70"/>
    </Grid>
  </Grid>
</Window>

My App.xaml code

<Application x:Class="Bingo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
  <Application.Resources>
    <Style TargetType="Label" x:Key="BNumber">
      <Setter Property="Content" Value="{Binding}"></Setter>
      <Setter Property="Background">
        <Setter.Value>
          <SolidColorBrush Color="Beige"/>
        </Setter.Value>
      </Setter>
    </Style>
  </Application.Resources>
</Application>

In my MainWindow.xaml.cs I have this List<String> BNumbers object and a Property that returns a random element of the BNumbers List

public MainWindow() {
  InitializeComponent();
  BNumbers.Add("1");
  BNumbers.Add("2");
  BNumbers.Add("3");
  BNumbers.Add("4");
  BNumbers.Add("5");
  BNumbers.Add("6");
  BNumbers.Add("7");
  BNumbers.Add("8");
  BNumbers.Add("9");
  BNumbers.Add("10");
  BNumbers.Add("11");
  BNumbers.Add("12");
  BNumbers.Add("13");
  BNumbers.Add("14");
  BNumbers.Add("15");
}
public string RandomBNumber {
  get { return randomB(); }
}
public string randomB() {
  Random rand = new Random();
  int randomBNumber = rand.Next(0, 15);
  return BNumbers[randomBNumber];
}
public List<String> BNumbers = new List<string>();
Zack
  • 2,789
  • 33
  • 60

2 Answers2

3

It maybe easier to randomize the list itself then each number as this will stop duplicates.

Aslo using a Uniform grid may be easier han adding a bunch of labels.

Example:

Xaml:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="346" Width="300" Name="UI">

    <Grid DataContext="{Binding ElementName=UI}">
        <ItemsControl ItemsSource="{Binding BNumbers}" Margin="0,29,0,0">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border Margin="1" BorderBrush="Black" BorderThickness="1" CornerRadius="2">
                         <Label Content="{Binding}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"  />
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="5" Rows="5"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
        <Button Content="New" Height="23" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
 </Window>

Code:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public List<string> AllNumbers { get; set; }
    private List<string> _bnumbers = new List<string>();

    public MainWindow()
    {
        InitializeComponent();
        AllNumbers = new List<string>();
        // Bingo game 75 numbers, 5x5 grid
        for (int i = 0; i < 75; i++)
        {
            AllNumbers.Add(i.ToString());
        }
    }

    public List<string> BNumbers
    {
        get { return _bnumbers; }
        set { _bnumbers = value; NotifyPropertyChanged("BNumbers"); }
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        RandomizeList(AllNumbers);
        BNumbers = AllNumbers.Take(25).ToList();
    }

    private void RandomizeList<T>(IList<T> list)
    {
        Random rng = new Random();
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = rng.Next(n + 1);
            T value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

Result ("New" will generate a new game)

enter image description here

sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • Thank you very much for spending time on helping me learn! I've never heard of the uniform grid before, but it sounds like it would work perfect, and be less mess than what I was trying to create. – Zack Jan 08 '13 at 15:01
  • I have [another question](http://stackoverflow.com/q/14282440/1804496) if you are up to it? – Zack Jan 11 '13 at 16:40
2

In the constructor, you need to set the DataContext:

this.DataContext = this;

You'll also need to change your setter to match the property name RandomBNumber :

<Setter Property="Content" Value="{Binding RandomBNumber }">
Greg Sansom
  • 20,442
  • 6
  • 58
  • 76
  • Thank you for your quick response O_O If I understand this right, `this.DataContext = this;` is setting the Window object's DataContext property to.. itself? – Zack Jan 07 '13 at 23:05
  • 1
    That's right :) You would usually set the DataContext to a ViewModel object, but using the Window is fine for the sake of learning/experimenting with binding. – Greg Sansom Jan 07 '13 at 23:09
  • I followed ssdam's suggestion and used UniformGrid's to display numbers selected at random inside an ItemsControl, I have [another question](http://stackoverflow.com/q/14282440/1804496) about accessing the items themselves if you have a moment – Zack Jan 11 '13 at 16:43