代码隐藏中的 WPF 应用程序访问控制

WPF application access controls in code-behind

我正在开发 WPF 记分应用程序。到目前为止 UI 已完成,但我无法访问代码隐藏中的任何控件。这是 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>

这是 C# 代码,它可能有更多我知道的错误,但它无法编译,因为它无法识别 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;
                    }
                }
            }
        }
    }
}
}

所有控件上都有一个 x:Name,但我只能访问其中的 2 个或 3 个,即使我可以,也没有任何反应。我想在文本框中写文本,在对文本框进行一些处理后,一些输出和统计数据应该显示在标签上,但它不允许我访问其中的任何内容,或者如果可以,它是随机的,什么也没有发生,就好像那里没有代码一样。

我在 xaml 中看不到您的 Window 声明的代码。但是由于您重命名了命名空间和 class,您应该在 xaml window 声明中包含它。

x:Class="Scoreboard.MainScoreBoard"

基本上你的 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="MainWindow" Height="350" Width="525">       

</Window>

你的代码背后确实有很多错误,因为你需要在几个地方调用 .ToString() 以及一些空引用异常,但如果你卡在那里,你总是可以 post 一个新问题。

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;
                    }
                }
            }               
        }
    }
}

xaml 中的那些样式未在任何地方定义,您应该在实现这些样式之前删除它们。我在编译时删除了它们,因为它们没有定义。

<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>