简体   繁体   中英

WPF application access controls in code-behind

I'm workin on a WPF scorekeeping app. So far the UI is done, but I can't access any of the controls in the code-behind. Here's the XAML:

<Window x:Class="Scoreboard.MainScoreBoard"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DartsLeague" Height="720" Width="1280">
    <Grid x:Name="MainGrid" Background="DarkGreen">
        <StackPanel x:Name="Player1" HorizontalAlignment="Left" VerticalAlignment="Stretch">
            <Label x:Name="Player1Name" Style="{StaticResource PlayerName}"/>
            <Label x:Name="Player1Score"  Style="{StaticResource Score}"/>
            <ScrollViewer x:Name="Player1Throws" Height="380" FlowDirection="RightToLeft">

            </ScrollViewer>
        </StackPanel>
        <StackPanel x:Name="Player2" HorizontalAlignment="Right" VerticalAlignment="Stretch">
            <Label x:Name="Player2Name" Style="{StaticResource PlayerName}">Player 2</Label>
            <Label x:Name="Player2Score" Style="{StaticResource Score}">501</Label>
            <ScrollViewer x:Name="Player2Throws" Height="380">

            </ScrollViewer>
        </StackPanel>
        <StackPanel x:Name="Input" HorizontalAlignment="Center"  VerticalAlignment="Top">
            <TextBox x:Name="CurrentNumber" MaxLength="3" Width="160" Margin="20" FontSize="30" TextChanged="TextBox_TextChanged"></TextBox>
            <Button x:Name="SubmitButton" IsDefault="True" Style="{StaticResource Golden} " Click="Button_Click">Запиши резултат</Button>
            <Button x:Name="CancelButton" Style="{StaticResource Golden}">Върни назад</Button>
        </StackPanel>
        <Grid x:Name="StatsGrid" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="60" Width="560">
            <StackPanel x:Name="Player1Stats" HorizontalAlignment="Left" VerticalAlignment="Stretch">
                <Label x:Name="Player1Legs" Style="{StaticResource BoardStats}"/>
                <Label x:Name="Player1Sets" Style="{StaticResource BoardStats}"/>
                <Label x:Name="Player1Avr" Style="{StaticResource BoardStats}"/>
            </StackPanel>
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Stretch">
                <Label Style="{StaticResource BoardStats}">LEGS</Label>
                <Label Style="{StaticResource BoardStats}">SETS</Label>
                <Label Style="{StaticResource BoardStats}">3 DART AVERAGE</Label>
            </StackPanel>
            <StackPanel x:Name="Player2Stats" HorizontalAlignment="Right" VerticalAlignment="Stretch">
                <Label x:Name="Player2Legs" Style="{StaticResource BoardStats}"/>
                <Label x:Name="Player2Sets" Style="{StaticResource BoardStats}"/>
                <Label x:Name="Player2Avr" Style="{StaticResource BoardStats}"/>
            </StackPanel>
        </Grid>
    </Grid>
</Window>

App.xaml:

<Application x:Class="Scoreboard.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Scoreboard"
             StartupUri="StartWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <Style x:Key="Golden" TargetType="Button">
                <Setter Property="Background" Value="Gold" />
                <Setter Property="BorderBrush" Value="Black" />
                <Setter Property="Margin" Value="10" />
                <Setter Property="Padding" Value="4" />
                <Setter Property="FontSize" Value="30" />
            </Style>

            <Style x:Key="PlayerName" TargetType="Label">
                <Setter Property="Background" Value="White" />
                <Setter Property="Margin" Value="10"/>
                <Setter Property="FontSize" Value="34" />
                <Setter Property="BorderBrush" Value="Black" />
                <Setter Property="BorderThickness" Value="2" />
                <Setter Property="HorizontalContentAlignment" Value="Center" />
            </Style>

            <Style x:Key="Score" TargetType="Label">
                <Setter Property="Margin" Value="10" />
                <Setter Property="Background" Value="White" />
                <Setter Property="FontSize" Value="160" />
                <Setter Property="BorderBrush" Value="Black" />
                <Setter Property="BorderThickness" Value="2" />
                <Setter Property="HorizontalContentAlignment" Value="Center" />
            </Style>

            <Style x:Key="BoardStats" TargetType="Label">
                <Setter Property="Background" Value="Beige" />
                <Setter Property="Margin" Value="4" />
                <Setter Property="BorderBrush" Value="DarkRed" />
                <Setter Property="BorderThickness" Value="4" />
                <Setter Property="HorizontalContentAlignment" Value="Center" />
                <Setter Property="FontSize" Value="26" />
                <Setter Property="Padding" Value="8" />
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Heres the C# Code, It probably has more bugs that I know of, but it won't compile because it doesn't recognize any of the names from the XAML:

namespace Scoreboard
{
     public partial class MainScoreBoard : Window
{
    public MainScoreBoard()
    {
        InitializeComponent();
    }

    static bool IsTextAllowed(string text, int num)
    {
        Regex regex = new Regex("[^0-9.-]+");
        if (!regex.IsMatch(text))
        {
            num = Int32.Parse(text);
            return true;
        }
        else return false;
    }

    void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {

    }


    void Button_Click(object sender, RoutedEventArgs e)
    {
        // You should get in the habit of initializing your variables
        int currentScore = 0, currentPlayerScore, currentResult, legs, sets;
        bool Player1Turn = true;

        // You were getting null reference exceptions from attempting to access the Content property
        // without them ever getting set.  You can initialize them with default values in the xaml or in the
        // constructor on initialization (After InitializeComponent() call).
        if (Player1Score.Content != null && Player2Score.Content != null)
        {
            bool isGameOver = false;

            // This will loop infinitely if you don't fix the bugs in calculating the score, I put a comment on it as you are not getting a value for currentScore from anywhere
            while (Int32.Parse(Player1Score.Content.ToString()) != 0 || Int32.Parse(Player2Score.Content.ToString()) != 0)
            {
                if (IsTextAllowed(CurrentNumber.Text, currentScore))
                {
                    if (currentScore > 180)
                    {
                        MessageBox.Show("Написаното е над 180!!!");
                        continue;
                    }
                    if (Player1Turn)
                    {
                        Player1Turn = false;

                        currentPlayerScore = Int32.Parse(Player1Score.Content.ToString());

                        // The currentScore variable is never getting set, I initialized it for you but
                        // it needs to be assigned a value from somewhere otherwise it will always be
                        // currentResult = currentPlayerScore - 0
                        currentResult = currentPlayerScore - currentScore;
                        if (currentResult < 0)
                        {
                            MessageBox.Show("Предобри!!!");
                            continue;
                        }
                        else if (currentResult == 0)
                        {
                            MessageBox.Show("Game Over!!!");
                            legs = Int32.Parse(Player1Legs.Content.ToString());
                            legs++;
                            Player1Legs.Content = legs.ToString();
                            if (legs == 3)
                            {
                                //increas sets
                                //if sets == 3, end game and shut down app 
                            }
                            //Application.Current.Shutdown();                             

                            // Set flag so we do not keep looping through game over code
                            isGameOver = true;
                        }

                        Player1Score.Content = currentResult.ToString();

                        // Added this check here because I'm assuming you would want Player1Score to be reflected first
                        // before exiting the loop.
                        if (isGameOver)
                        {
                            // game is over, we do not want to keep showing the Game Over message box
                            break;
                        }
                    }
                    else
                    {
                        //the same for Player2
                        Player1Turn = true;
                    }
                }
            }
        }
    }
}
}

All of the controls have an x:Name on them, but I can access only 2 ot 3 of them, and even if I can, nothing happens. I want to write text in the textbox, and after some processing goes on with the textbox, some output and stats are supposed to show up on the labels, but it won't let me access any of it, or if it does, it's random, and nothing happens, as if there is no code there.

I cannot see the code for your Window declaration in the xaml. But since you renamed the namespace and class, you should have this in your xaml window declaration.

x:Class="Scoreboard.MainScoreBoard"

Essentially your xaml should look like this

<Window x:Class="Scoreboard.MainScoreBoard"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">       

</Window>

You do have a lot more bugs in the code behind as you need to call .ToString() in several places as well as some null reference exceptions, but if you get stuck in there you can always post a new question.

public partial class MainScoreBoard : Window
{
    public MainScoreBoard()
    {
        InitializeComponent();
    }

    static bool IsTextAllowed(string text, int num)
    {
        Regex regex = new Regex("[^0-9.-]+");
        if (!regex.IsMatch(text))
        {
            num = Int32.Parse(text);
            return true;
        }
        else return false;
    }

    void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {

    }


    void Button_Click(object sender, RoutedEventArgs e)
    {
        // You should get in the habit of initializing your variables
        int currentScore = 0, currentPlayerScore, currentResult, legs, sets;
        bool Player1Turn = true;

        // You were getting null reference exceptions from attempting to access the Content property
        // without them ever getting set.  You can initialize them with default values in the xaml or in the
        // constructor on initialization (After InitializeComponent() call).
        if (Player1Score.Content != null && Player2Score.Content != null)
        {
            bool isGameOver = false;

            // This will loop infinitely if you don't fix the bugs in calculating the score, I put a comment on it as you are not getting a value for currentScore from anywhere
            while (Int32.Parse(Player1Score.Content.ToString()) != 0 || Int32.Parse(Player2Score.Content.ToString()) != 0)
            {
                if (IsTextAllowed(CurrentNumber.Text, currentScore))
                {
                    if (currentScore > 180)
                    {
                        MessageBox.Show("Написаното е над 180!!!");
                        continue;
                    }
                    if (Player1Turn)
                    {
                        Player1Turn = false;

                        currentPlayerScore = Int32.Parse(Player1Score.Content.ToString());

                        // The currentScore variable is never getting set, I initialized it for you but
                        // it needs to be assigned a value from somewhere otherwise it will always be
                        // currentResult = currentPlayerScore - 0
                        currentResult = currentPlayerScore - currentScore;
                        if (currentResult < 0)
                        {
                            MessageBox.Show("Предобри!!!");
                            continue;
                        }
                        else if (currentResult == 0)
                        {
                            MessageBox.Show("Game Over!!!");                                
                            legs = Int32.Parse(Player1Legs.Content.ToString());
                            legs++;
                            Player1Legs.Content = legs.ToString();
                            if (legs == 3)
                            {
                                //increas sets
                                //if sets == 3, end game and shut down app 
                            }
                            //Application.Current.Shutdown();                             

                            // Set flag so we do not keep looping through game over code
                            isGameOver = true;
                        }

                        Player1Score.Content = currentResult.ToString();

                        // Added this check here because I'm assuming you would want Player1Score to be reflected first
                        // before exiting the loop.
                        if (isGameOver)
                        {
                            // game is over, we do not want to keep showing the Game Over message box
                            break;
                        }
                    }
                    else
                    {
                        //the same for Player2
                        Player1Turn = true;
                    }
                }
            }               
        }
    }
}

Those styles in the xaml are not defined anywhere you should remove them until you implement the styles. I removed them when compiling as they are not defined.

<Window x:Class="Scoreboard.MainScoreBoard"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Scoreboard"
    Title="DartsLeague" Height="720" Width="1280">
<Grid x:Name="MainGrid" Background="DarkGreen">
    <StackPanel x:Name="Player1" HorizontalAlignment="Left" VerticalAlignment="Stretch">
        <Label x:Name="Player1Name"/>
        <Label x:Name="Player1Score">501</Label>
        <ScrollViewer x:Name="Player1Throws" Height="380" FlowDirection="RightToLeft">

        </ScrollViewer>
    </StackPanel>
    <StackPanel x:Name="Player2" HorizontalAlignment="Right" VerticalAlignment="Stretch">
        <Label x:Name="Player2Name">Player 2</Label>
        <Label x:Name="Player2Score">501</Label>
        <ScrollViewer x:Name="Player2Throws" Height="380">

        </ScrollViewer>
    </StackPanel>
    <StackPanel x:Name="Input" HorizontalAlignment="Center"  VerticalAlignment="Top">
        <TextBox x:Name="CurrentNumber" MaxLength="3" Width="160" Margin="20" FontSize="30" TextChanged="TextBox_TextChanged"></TextBox>
        <Button x:Name="SubmitButton" IsDefault="True" Click="Button_Click">Запиши резултат</Button>
        <Button x:Name="CancelButton">Върни назад</Button>
    </StackPanel>
    <Grid x:Name="StatsGrid" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="60" Width="560">
        <StackPanel x:Name="Player1Stats" HorizontalAlignment="Left" VerticalAlignment="Stretch">
            <Label x:Name="Player1Legs">0</Label>
            <Label x:Name="Player1Sets" />
            <Label x:Name="Player1Avr" />
        </StackPanel>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Stretch">
            <Label>LEGS</Label>
            <Label>SETS</Label>
            <Label>3 DART AVERAGE</Label>
        </StackPanel>
        <StackPanel x:Name="Player2Stats" HorizontalAlignment="Right" VerticalAlignment="Stretch">
            <Label x:Name="Player2Legs"/>
            <Label x:Name="Player2Sets"/>
            <Label x:Name="Player2Avr" />
        </StackPanel>
    </Grid>
</Grid>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM