Change MainWindow content from other pages - c#

In my main window in WPF application I have a Badged element (from material design)
This is my code:
<materialDesign:Badged BadgePlacementMode="Left"
Name="RequestBadge"
Badge="3"
VerticalAlignment="Center">
<Button Content="Show Requests" ..... />
</materialDesign:Badged>
I want to change Badge content dynamically.
I add this function in code-behind:
public void setBadge(int num)
{
RequestBadge.Badge = num;
}
But when I try to call this function from other pages, I get this error:
An object reference is required for the non-static field, method, or property PL.MainWindow.setBadge(int)

you need to find an open instance of MainWindow:
var mw = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
mw?.SetBadge(counter);

The fastest solution would be to use a singleton pattern to access your MainWindow and with this create a static method in your MainWindow that sets your badge:
private static MainWindow _instance;
public MainWindow()
{
_instance = this;
...
}
public static void SetBadge(int num)
{
_instance.setBadge(num);
}

Related

How to change property for UI Element from another c# file?

I have a program with MainWindow.xaml, MainWindow.xaml.cs, and Helper.cs files. All the UI is in the .xaml file and can only be accessed from the .xaml.cs file. But now I want to change the text in a TextBox in the MainWindow.xaml file from the Helper.cs file, which is completely separate.
I've tried creating a function in MainWindow.xaml.cs to do that:
public void SetRNrInfoText(string value)
{
this.RNrInfoTextBox.Text = value;
}
or
public string RNrInfoText
{
get { return this.RNrInfoTextBox.Text; }
set { this.RNrInfoTextBox.Text = value; }
}
In Helper.cs file, I use:
public static void searchByRNR()
{
MainWindow mainWindow = new MainWindow();
mainWindow.SetRNrInfoText("new text");
}
However, when I try to call this searchByRNR function, nothing happens. In the .xaml file, "x:FieldModifier" is set to "public".
For now, the only idea I have is to make Helper return a dictionary or an array, and then in MainWindow, set all the values to certain textboxes, but I don't really like that idea.
So the question is, can I somehow change the property of a .xaml element in another .cs file, or is it not possible?"
MainWindow mainWindow = new MainWindow(); creates a new instance of the MainWindow class which is not what you want.
You need to get a reference to the already existing instance of the MainWindow in your Helper class somehow.
The easiest way to do this is probably to change the modifier of the m_window field in App.xaml.cs as suggested here.
You can then get a reference to the window in your Helper class like this:
public static void searchByRNR()
{
MainWindow mainWindow = (Application.Current as App)?.m_window as MainWindow;
mainWindow.SetRNrInfoText("new text");
}

WPF Control Disposal

In WinForms, for all controls there is the .OnDisposed override, the Disposed event, and the IsDisposed property.
WPF seems to have no equivalent.
How can I listen for the disposal of a UserControl in a WPF application?
To be more clear; I need to know when the control is removed. The reason being that for some controls I want to keep a static reference to the control for easier access to it, and when the control is no longer in scope, I need to set that reference to null.
To be even more clear :
public class Foo : UserControl{
private static Foo _Instance;
//For ease of access. I do not want to have to call Control.Control.Control.Control.FooVar.DoSomething() when I can call Foo.Instance.DoSomething()
public static Foo Instance { get { return Foo._Instance ?? new Foo() } }
public Foo(){
this.InitializeComponents();
/*Other Initialization Stuff*/
Foo._Instance = this; /*<---- This needs to be set to null when Foo is closed/disposed/removed/out of scope etc.*/
}
}
If you want to statically reference objects, but without keeping them in-memory, you could always elect for a WeakReference<T>
public partial class MyControl : UserControl
{
private readonly static WeakReference<MyControl> _instance
= new WeakReference<T>(null);
public static MyControl Instance
{
get
{
UserControl result;
if(!_instance.TryGetTarget(out result))
_instance.SetTarget(result = new MyControl());
return result;
}
}
}
This, however, introduces the possibility that, depending on the whims of the GC, you may get the same control after quickly closing and refreshing a page. In such case, you should make sure the Unloaded event triggers a nullification of the instance
// Ensure the instance is cleared when unloading
public void OnUnloaded(object sender, RoutedEventArgs args)
{
_instance.SetTarget(null);
}
and then in your XAML...
<UserControl ...
Unloaded="OnUnloaded">

object reference is null

There is one MainWindow and one user-control in my WPF application. I want to call function of my MainWindow in user-control, without creating new instance of MainWindow. For this i made main-window parent of user-control. I wrote this code below for calling function of Parent.
Child User-Control
public partial class AppLogo : UserControl
{
public MainWindow myparent { get; set; }
private void activate_Click_1(object sender, RoutedEventArgs e)
{
myparent.function();
}
. . .
}
Parent Window:
public MainWindow()
{
InitializeComponent();
AppLogo childWindow = new AppLogo();
. . .
Questions:
Is It Possible to create Window a parent of user-control?
If answer of above question is Yes then why it is generating error that Object Reference is Null.
If answer is No it is not possible then how can i achieve this goal. As it is necessary to create user-control in my application as it is requirement.
If you want to have reference in UserControl to MainWindow use following code:
MainWindow mw = Application.Current.MainWindow as MainWindow;
http://msdn.microsoft.com/en-us/library/system.windows.application.mainwindow.aspx
private void activate_Click_1(object sender, RoutedEventArgs e)
{
MainWindow mw = Application.Current.MainWindow as MainWindow;
if(mw != null)
{
mw.function();
}
}
Second solution:
In your code you should set myparent property in MainWindow constructor:
public MainWindow()
{
InitializeComponent();
AppLogo childWindow = new AppLogo();
childWindow.myparent = this;
...
}
In activate_Click_1 event handler the good habit is check if myparent is not null:
private void activate_Click_1(object sender, RoutedEventArgs e)
{
if(myparent != null)
myparent.function();
else
...
}
I'm assuming that the null reference is for the myparent property on AppLogo?
After this line AppLogo childWindow = new AppLogo(); add one saying childWindow.myparent = this;
You may introduce a child parent dependecy as suggested, however since you didn't instantiate MainWindow you should expect a null reference exception when calling myparent.function();
First, you need to instantiate MainWindow, and then set the child parent relationship by calling AppLogo .set_myparent, only then your call won't fail.
You need to pass a reference to the instance of MainWindow as an argument to AppLogo's constructor, then set it to AppLogo's variable for MainWindow.
public AppLogo(MainWindow mainWindow)
{
this.myparent = mainWindow;
}
If you locate your UserControl directly inside your Window, then its Parent property will reference your window.
The exception is called when you try to access the field which contains null value. It contains null because noone placed there anything else. You might want to set it:
AppLogo childWindow = new AppLogo();
childWindow.myparent = <something>;
You just need to recursively search your UserControl's parents until you get an instance of a Window, which will be your goal.
public static Window GetWindow(FrameworkElement element)
{
return (element.Parent as Window) ?? GetWindow(element.Parent);
}

Calling other class function

I have a grid class and a MainWindow class. Grid's class function needs to call MainWindow's function:
// function from grid class:
public Point functionFromGridClass()
{
Point variable = MainWindow.functionFromMainWindowClass(0, 0);
// ...
}
// function from MainWindow class:
public static Point functionFromMainWindowClass(int x, int y)
{
Vector2 mouse;
mouse.X = x;
mouse.Y = y + (ClientRectangle.Height - glview.Size.Height);
// ...
}
If I remove static keyword in functionFromMainWindowClass, then I can't call it from grid class. If I don't remove static keyword, then I can't use the MainWindow's class variables ClientRectangle and glview, I get a warning "An object reference is required for the non-static field, method, or property". I've never faced this problem, what should be the solution?
The grid class has to hold a reference of an instance of the MainWindow and probably provided to grid upon construction.
public class GridClass
{
private MainWindow window;
public GridClass( MainWindow Window)
{
window = Window;
}
public Point functionFromGridClass()
{
Point variable = window.functionFromMainWindowClass(0, 0);
}
}
I get a warning "An object reference is required for the non-static field, method, or property"
The warning tells you what to do: you need an instance in order to call instance methods.
So you could remove the static keyword from the method and then in your Grid class create an instance of MainWindow in order to be able to call the method:
var mainWindow = new MainWindow();
var result = mainWindow.functionFromMainWindowClass(5, 6);
It's hard to give specific advice without knowing exactly what is going on, but the general picture is that you need to somehow get the instance of the MainWindow class that you want to call the method on, either by passing it into Grid at construction or similar, or by getting it from some resource manager.
Static methods are called with reference of the className.
Call you Main window class function like this:
public Point functionFromGridClass()
{
MainWindowClass.functionFromMainWindowClass(val1, val2);
}

object reference is required for the non-static field, method, or property

hmm I seem to have a problem, on my main window I am trying to do this:
public static readonly DependencyProperty StudentIDProperty = DependencyProperty.Register("StudentID", typeof(String), typeof(LoginWindow), new PropertyMetadata(OnStudentIDChanged));
public string StudentID
{
get { return (string)GetValue(StudentIDProperty); }
set { SetValue(StudentIDProperty, value); }
}
static void OnStudentIDChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as LoginWindow).OnStudentIDChanged(e); //
}
On my other window I have this:
MainWindow.StudentID = (String)((Button)sender).Tag;
But I get the error:
An object reference is required for the non-static field, method, or property 'WpfApplication4.MainWindow.StudentID.get'
Does anyone know how I can fix this? It works for my user controls but not other windows?
My main window is actually named MainWindow so I may have had this confused.
You need to set StudentID on an instance of your MainWindow class. Try
((MainWindow)Application.Current.MainWindow).StudentID = (String)((Button)sender).Tag;
Because MainWindow is the name of your class, not an instance of MainWindow. You need something like:
MainWindow mw = new MainWindow();
mw.StudentID = (String)((Button)sender).Tag;
I was trying to update a TextBox in the MainWindow from a UserControl and get the error
Error 1: An object reference is required for the non-static field, method, or property
'WpfApplication1.MainWindow.textBox1'
I resolved this error by writing the following:
//MainWindow.textBox1.Text = ""; //Error 1
((MainWindow)Application.Current.MainWindow).textBox1.Text = "";//This is OK!
This was suggested by Rytis I

Categories

Resources