How to use WPF elements from another class? - c#

I'm currently developing a chat client/server with a WPF visual interface. One of the main function in the MainWindow class is designed to write a message in a richbox in the related WPF.
public partial class MainWindow : Window
{
// VU Window
public static MainWindow vuClient;
// VU Initialization
public MainWindow()
{
InitializeComponent();
vuClient = this;
}
static public void writeChat(User pUser, String pMessage)
{
...
// Writing in the richbox
vuClient.vuChatBox.Document.Blocks.Add(formatedMessage);
}
}
The problem is that if I call writeChat() in the MainWindow() function or through an event (onclick for example) everything works as attended, but if I try to call this function via an other class nothing happens! I don't even have an error. Do you have any clue about that issue?

No need to maintain the object "vuClient". Because writeChat is a static method.
You can directly called like below
MainWindow.writeChat();

you can't use an UI element or a function in some other class. you need to make a Delegate with an event. with the help of this event you can update your UI accordingly.

Related

C# - Unable to add item to listview from method invoked from class

Im having a strange problem with my programme, whenever I call a method from another class, it doesnt work as expected. Basically, what I am trying to do is add an item to a listview, and the code is in a method, and I am trying to invoke that method from another class. Here is my code:
public class Main1
{
public void addItemToLV(string text)
{
listView1.Items.Add(text);
}
}
public class MainForm
{
Main1 m1 = new Main1();
m1.addItemToLV("test");
}
Any ideas why this is happening? Thanks.
Under normal circumstances, the controls on a form are declared as protected properties within the designer.cs file rather than public properties, so those controls will normally not be accessible to code outside of the form on which they are declared. This is intentional, as it encourages good object-oriented programming habits.
Rather than modifying a control directly from code that exists outside the form, a better practice is to declare public methods and properties within your form that can be called from outside code to manipulate the protected controls:
public class Main1
{
public static void Main()
{
var mainForm = new MainForm();
mainForm.AddItemToListView("test");
}
}
public class MainForm
{
public void AddItemToListView(string text)
{
listView1.Items.Add(text);
}
}
You could try to pass the ListView as an argument in the constructor and make the function return this ListView to your MainWindow.
public class Main1
{
private readonly ListView _lv;
public Main1(ListView listview)
{
_lv = listview;
}
public ListView addItemToLV(string text)
{
_lv.Items.Add(text);
return _lv;
}
}
I think your code sample is not enough but I am trying to guess the reason behind the issue and I think it is one of the following:
1.You are initialising your listView1 in the load event of Main1, and you are trying to show the form after calling the method. In that case you should call the method after showing the Main1 form.
2. Or simply you are trying to call the method on a different instance than the one displayed.

WPF Caliburn.Micro : Life Cicyle problems

I have a class called AppViewModel, this class it's responsible to control the screens. AppViewModel extends my BaseConductor:
public class BaseConductor : Conductor<Screen>.Collection.OneActive
{
...
}
Then, I call a viewmodel (UserControl) on the constructor of AppViewModel:
this.ActivateItem(new FirstViewModel());
On FirstViewModel, after the user clicks on a button I want to open SecondViewModel and close the FirstViewModel:
var conductor = this.Parent as IConductor;
conductor.DeactivateItem(this, true);
conductor.ActivateItem(new SecondViewModel(param));
I already tried to do this:
((IApp)this.Parent).ActivateItem(new SecondViewModel(param));
TryClose();
SecondViewModel extends my BaseScreen:
public class BaseSceen : Screen
{
...
}
I want to close the FirstViewModel, because on the FirstViewModel and SecondViewModel I have shortcuts. When I'm with the SecondViewModel opened I hit a shortcut, and the method that is executed it's from FirstViewModel. So, the FirstViewModel still running.
How can I close the FirstViewModel, and avoid this problem with shortcuts?
Thanks!
Do you really need to use Conductor<T>.Collection.OneActive? You can just use Conductor<T> so that activating an item will automatically deactivate and close the previously active item. And also, is it required that the button/action pair reside in the FirstViewModel? I suggest that you just put those in the AppViewModel and let it orchestrate the navigation and activation/deactivation of the two child screens.
public AppViewModel : Conductor<Screen>
{
public void AppViewModel()
{
ActivateItem(new FirstViewModel());
}
public void ActivateSecondViewModel()
{
// FirstViewModel will automatically be deactivated
// and closed since we are using plain Conductor<T>
ActivateItem(new SecondViewModel());
}
}
I found it! The shortcut event was attached to the window, not to the usercontrol.
So, event when usercontrol was ended the event still "attached" to the window. Now, I added an method that is called when UserControl is Unloaded, to "deattach" the event.
Bad mistake!

use Winform Objects inside an Static Method

I have a problem that I could ignore a long time but now I have to solve it.
I have 3 GUI (Winform) 1 Main 1 Settings and 1 for a Webbrowser.
I need to call a Method that is in my Webbrowser Form inside my Main Form for that reason the Method is a static one.
But if I set it to static it giveĀ“s me an error if I try to work with the Objects from the Form.
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
public static void WebLyrics(string url){
webBrowser1.Navigate(url);
}
}
The easiest way is to:
Add a static Instance property to the webbrowser form:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
Instance = this;
}
public static Form3 Instance { get; private set; }
public void WebLyrics(string url)
{
webBrowser1.Navigate(url);
}
}
and call the WebLyrics method via the Instance property in the other form:
public partian class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Navigate()
{
Form3.Instance.WebLyrics("www.stackoverflow.com");
}
}
I assumed you create both forms somewhere somehow...
You should consider changing the code. Why is your Form having a static method? It doesn't make any sense. The easiest way to achieve it is to pass reference to the Webbrowser Form into the Main Form. Or you can instantiate the Webbrowser form inside you Main Form and then show it.
But I suggest that you introduce a way of separating the UI from the business logic layer. Consider to introduce MVC / MVP pattern, to have a clear separation, and then the forms do not need to have references to each other directly.
The easiest (= least code) way to solve it is probably to use singletons for the forms as other have suggested, or even simpler to use the built in forms registry:
var myForm3 = Application.OpenForms.OfType<Form3>.FirstOrDefault();
I would probably prefer to use a separate singleton for holding the forms, as I would find it more maintainable. This would be a better separation of concerns in that the forms would not have to be created as singletons and could be reused in other ways. It is truly your app's UI layout that is the singleton.
Something like this:
public class AppLayout
{
public static AppLayout Instance {
get { ... }
}
public WebBrowserForm WebBrowser {get;private set;}
public MainForm Main {get;private set;}
public SettingsForm Settings {get;private set;}
}
Think of it like a typed variant of the Application singleton.

Call panel.invalidate outside form class in C#

I need to call "panel.invalidate" outside my form (WINform) class also I need to change some other controls as well, I read similar question here, and tried what they said, but it didn't work and I wasn't convinced at all.
The answer I read was about exposing a public method like this:
public void EnableButton(bool enable)
{
this.myButton.Enabled = enable;
}
Also I made a static instance in the other file
static Form1 myForm = new Form1();
Any useful suggestions??
The problem is the "myForm" reference. It is a reference to an instance of Form1 that isn't visible and doesn't match the one that the user is looking at. It can't be a match, you created a new one.
Whatever class needs to update the form must have a constructor that takes a Form1 reference. You can create the class object in your Form1 constructor or Load event, pass "this". Using Application.OpenForms[0] is another way to get the reference, one you should not use.
Are you updating from the same thread? Otherwise you might need to use Invoke.
Here's a nice short article about how to do that:
http://blogs.msdn.com/csharpfaq/archive/2004/03/17/91685.aspx
Control.Invalidate() is a public method, but the control itself is most likely not public. You will have to expose the call to Control.Invalidate() through a public facing method in your form or by marking the control in question as public.
public class MyForm : Form {
private TextBox tbxName = new TextBox();
public InvalidateTextBox() {
tbxName.Invalidate();
}
}
OR
public class MyForm : Form {
public TextBox tbxName = new TextBox();
}
public class SomeOtherClass {
public void InvalidateTextBox(MyForm form) {
form.tbxName.Invalidate();
}
}

shared functionality on usercontrol and form

I need to add shared functionality to both Forms and UserControls. Since multiple inheritance isn't supported in .net I wonder how I best tackle this?
The shared functionality is a dictionary that is filled by the form or usercontrol and then processed.
Regards
public class SharedFunctionality
{
public void ImportantToCallThisOnLoad();
}
public class MyForm : Form
{
SharedFunctionality mySharedFunctionality = new SharedFunctionality();
public void OnLoad()
{
mySharedFunctionality.ImportantToCallThisOnLoad();
}
}
public class MyControl : Control
{
SharedFunctionality mySharedFunctionality = new SharedFunctionality();
public void OnLoad()
{
mySharedFunctionality.ImportantToCallThisOnLoad();
}
}
Instead of having the Forms & UserControls inherit from a base class can you encapsulate the logic inside of a self contained object so that each form will new up? Then you can limit in the base class just the instantion and interaction with this object which hopefuly is minimal so having it done twice isn't a big deal.

Categories

Resources