简体   繁体   中英

C# Error: Object reference is required for the non-static field, method, or property

I need a little help here. I am trying to have the Latitude and Longitude values populate 2 textboxes in my WPF application. Now I can get the values to show up in a MessageBox all formatted the way I need it to appear in the text boxes.

However when I try to send the data to the textboxes I am getting

"An object reference is required for the non-static field, method, or property 'Registration.tbXCoords'.

Any help would be greatly appreciated.

//Registration.xaml.cs     

using System.Windows;
using System.Device.Location;
using System;

namespace Battle_Sample
{

public partial class Registration : Window
{
    public Registration()
    {
        WindowStartupLocation = WindowStartupLocation.CenterScreen;
        InitializeComponent();
        CLocation myLocation = new CLocation();
        myLocation.GetLocationEvent();
    }

    public class CLocation
    {
        GeoCoordinateWatcher watcher;

        public void GetLocationEvent()
        {
            this.watcher = new GeoCoordinateWatcher();
            this.watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
            bool started = this.watcher.TryStart(false, TimeSpan.FromMilliseconds(1000));
            if (!started)
            {
                MessageBox.Show("GeoCoordinateWatcher timed out on start.");
            }
        }

        public void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            PrintPosition(e.Position.Location.Latitude, e.Position.Location.Longitude);
        }

        public void PrintPosition(double Latitude, double Longitude)
        {
            MessageBox.Show("X: " + Latitude.ToString("0.00") + ", Y: " + Longitude.ToString("0.00"));

            //The following two lines are where I am getting the error
            tbXCoords.Text = (Latitude.ToString());
            tbYCoords.Text = (Longitude.ToString());
        }
    }
  }
}




//Registration.xaml

<Window x:Class="Battle_Sample.Registration"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Battle_Sample"
    mc:Ignorable="d"
    Title="Battle Registration" Height="300" Width="300">

<Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="4*"/>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <StackPanel Grid.Column="0" Grid.Row="3">
        <TextBlock FontWeight="Bold" Text="Location:" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,6,0,0" />
    </StackPanel>

    <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="3">
        <TextBlock Margin="2" VerticalAlignment="Center">X</TextBlock>
        <TextBox x:Name="tbXCoords" Margin="5" Width="50" IsEnabled="False" />
    </StackPanel>

    <StackPanel Orientation="Horizontal" Grid.Column="2" Grid.Row="3">
        <TextBlock Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center">Y</TextBlock>
        <TextBox x:Name="tbYCoords" Margin="5" Width="50" IsEnabled="False" />
    </StackPanel>
</Grid>

tbXCoords and tbYCoords are fields defined in your Registration class and, as the error message is telling you, they are not static therefore in order to access them, you need to specify an actual reference to the Registration object that "owns" them.

You are essentially doing something equivalent to:

public class A
{
    public string Hello = "Hello";

    public class B
    {
        //Hello of what A?
        public void SayHello() { 
            Console.Write(Hello); } //Error  
    }
}

Which is obviously wrong. What you need to do is:

public class B
{
    //Specify what specific A's Hello you want.
    public void SayHello(/*A a*/) {
        Console.Write(a.Hello); }   
}

a can be a local, a field, a method argument, a property, etc., but it needs to be a variable pointing to a concrete A object (or a null reference in which case your code will compile but fail in runtime).

In order to fully understand the error message you are getting, consider the case where Hello is static:

public class A
{
    public static string Hello = "Hello";

    public class B
    {
        public void SayHello() { 
            Console.Write(Hello); }  
    }
}

Now this code will compile just fine because the field Hello is now "owned" by the type A itself and not by concrete instances of A ; there is only one Hello for all A s (this is a pretty informal description of what a static field really is but it should get a reasonably correct mental picture across).

Ok, enough chit chat, how do you solve this? Well without knowing too much of your code, a reasonable way is telling your concrete CLocation instance what concrete Registration owns it via a constructor:

public Registration()
{
    WindowStartupLocation = WindowStartupLocation.CenterScreen;
    InitializeComponent();
    CLocation myLocation = new CLocation(this);
    myLocation.GetLocationEvent();
}

public class CLocation
{
     private readonly Registration registrationWindow;

     public CLocation(Registration registrationWindow) {
         this.registrationWindow = registrationWindow; }

     //...

    public void PrintPosition(double Latitude, double Longitude)
    {
        //...
        registrationWindow.tbXCoords.Text = (Latitude.ToString());
        registrationWindow.tbYCoords.Text = (Longitude.ToString());
    }
}

Now this might be an overkill if you only need the reference inside your PrintPosition method. In that case you can consider specifying the concrete window instance as an argument:

public void PrintPosition(Registration registrationWindow,
                          double Latitude, 
                          double Longitude)
{
    //...
    registrationWindow.tbXCoords.Text = (Latitude.ToString());
    registrationWindow.tbYCoords.Text = (Longitude.ToString());
}

Again, you should know what fits better in your specific scenario.

I don't know why did you put "GeoLocation" code in the different class. But you can fix it like this using the events:

public partial class Registration: Window
{
    public Registration()
    {
        InitializeComponent();
        WindowStartupLocation = WindowStartupLocation.CenterScreen;
        InitializeComponent();
        CLocation myLocation = new CLocation();
        myLocation.OnPositionChanged += new EventHandler<PositionEventArgs>(myLocation_OnPositionChanged);
        myLocation.GetLocationEvent();

    }

    private void myLocation_OnPositionChanged(object sender, PositionEventArgs e)
    {
        tbXCoords.Text = (e.Latitude.ToString());
        tbYCoords.Text = (e.Longitude.ToString());
    }

    public class CLocation
    {
        public EventHandler<PositionEventArgs> OnPositionChanged;
        GeoCoordinateWatcher watcher;

        public void GetLocationEvent()
        {
            watcher = new GeoCoordinateWatcher();
            watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
            bool started = this.watcher.TryStart(false, TimeSpan.FromMilliseconds(1000));
            if (!started)
            {
                MessageBox.Show("GeoCoordinateWatcher timed out on start.");
            }
        }

        public void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            OnPositionChanged?.Invoke(this, new PositionEventArgs() { Latitude = e.Position.Location.Latitude, Longitude = e.Position.Location.Longitude });
        }
    }
}

and this is the PostionEventArgs class:

public class PositionEventArgs
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

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