1

Hello I have a simple WPF window and I want to load and display a logo image on specific "Image" item. The following code works perfectly and I can display the logo.

namespace WPFexample
{
    public partial class MainWindow : Window
    { 
        public MainWindow()
        {
            InitializeComponent();
            var uri = new Uri("pack://application:,,,/Assets/Logo.png");
            LogoImage.Source = new BitmapImage(uri);
        }
    }
}

Now I want to create another class which can access the GUI and display from there the logo:

namespace WPFexample
{
    public partial class MainWindow : Window
    { 
        public MainWindow()
        {
            InitializeComponent();                
        }
    }

    class MyClass
    {
        private void myCustomDisplay()
        {
            var uri = new Uri("pack://application:,,,/Assets/Logo.png");
            // How can I call the LogoImage.Source from this place??
        }
    }
}

Initially I thought that I could do this but nothing happened:

class MyClass
{   
    private void myCustomDisplay()
    {
        MainWindow MainWindowClassRef = new MainWindow();
        var uri = new Uri("pack://application:,,,/Assets/Logo.png");
        MainWindowClassRef.LogoImage.Source = new BitmapImage(uri);
    }
}

Any suggestion why I cannot display it?

This does not work either:

namespace WPFexample
{
    public partial class MainWindow : Window
    { 
        public MainWindow()
        {
            InitializeComponent();                
        }
        public void DisplayInGUI()
        {
            var uri = new Uri("pack://application:,,,/Assets/ITLLogo.png");
            LogoImage.Source = new BitmapImage(uri);            
        }
    }

    class MyClass:MainWindow 
    {
        public void myCustomDisplay()
        {
            DisplayInGUI()
        }
    }
}
Saadi
  • 2,211
  • 4
  • 21
  • 50
Spyros
  • 261
  • 2
  • 14
  • In what thread is myCustomDisplay() used? Is it on the dispatcher thread? Anyway, it's unclear where you want the logo: displayed in this new "class"? What is this new class? A distinct Control or is this a part of the MainWindow? – nkoniishvt Jun 07 '16 at 08:59
  • *"I want to create another class which can access the GUI"* - can you explain this in details? What is the role of this class? To update something in `MainWindow`? Then extend `MainWindow` with public method and call it (you will have to pass `MainWindow` instance around). – Sinatr Jun 07 '16 at 09:08
  • 1
    `((MainWindow)Application.Current.MainWindow).DisplayInGUI()` should work. You should however read up on `MVVM`, the standard architectural pattern for WPF applications, and then create a view model with a property for the logo image. – Clemens Jun 07 '16 at 09:11
  • I want to create something like a library that I can move around in different GUIs, where I will have some methods that I use. The role of this new Class is to make all the processing of an image, and I just need the MainWindow for displaying the Image result. So the new class I want to make is more or less independent of the GUI, I just need to be able to call the GUI only for displaying. – Spyros Jun 07 '16 at 09:11
  • 1
    If you want to use it on any MainWindow/Control you'll want to create an Image style which set its source to your image. You could put that style and the logo in a dll and import the Style every time you need it, just set the Image's Style each time or put the Style in the app.xaml – nkoniishvt Jun 07 '16 at 09:18
  • @Clemens Thank you for your answer. It works perfectly. Thank you also for mentioning the MVVM. I shall study it. Could you please post you comment as an answer so I can up-vote it and close this question. Thank you, – Spyros Jun 07 '16 at 09:18
  • @nkoniishvt The new class I want to make is a distinct Control and not part of the MainWindow. I just need to use the MainWindow only for displaying stuff. – Spyros Jun 07 '16 at 09:22
  • @Spyros Ok so one thing: If you put that Control in a dll this will probably not work: it won't know MainWindow's type which isn't a standard type, only the default one created by Visual Studio. If you put a MainWindow in that dll with your distinct Control you'll have to use the MainWindow of that dll in each project or the (MainWindow) cast won't work (InvalidCastException): the two types may have the same names but won't be the same types. – nkoniishvt Jun 07 '16 at 09:25
  • @nkoniishvt Thank you for explaining that I understand now. I have a long way still, until I make this class a .dll. For now I will always just have it as a class which I will import in different projects and manually change the methods and classes names accordingly. (As you can tell I am a new C# programmer and still I have many things to learn). – Spyros Jun 07 '16 at 09:31

2 Answers2

1

To access a member (e.g. property or method) of the MainWindow instance, you can cast the MainWindow property of the current Application instance to your MainWindow class.

So e.g. call the MainWindow's DisplayInGUI() method by

((MainWindow)Application.Current.MainWindow).DisplayInGUI();

You probably want to pass the actual logo image as parameter to a method like

public partial class MainWindow : Window
{ 
    ...
    public void SetLogoImage(ImageSource image)
    {
        LogoImage.Source = image;
    }
}

and call it like this:

((MainWindow)Application.Current.MainWindow).SetLogoImage(
    new BitmapImage(new Uri("pack://application:,,,/Assets/ITLLogo.png")));

EDIT: Call the method from another thread like this:

var mainWindow = (MainWindow)Application.Current.MainWindow;
mainWindow.Dispatcher.Invoke(() => mainWindow.DisplayInGUI());
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • Thank you for your answer. If I want to call the DisplayInGUI() from another thread , how shall I call the dispatcher using casting? Is it even possible? – Spyros Jun 07 '16 at 09:33
  • Shall it be like this: MainWindowClassRef .Dispatcher.Invoke((Action)(() => { ((MainWindow)Application.Current.MainWindow).DisplayInGUI(); })); – Spyros Jun 07 '16 at 09:39
0

MyClass needs to have a property or field called LogoImage. The "partial" keyword indicates that MainWindow has part of its class definition somewhere else - probably in a class called MainWindow.xaml. I would try looking at that file and moving the relevant portions of it to MyClass.

It might also help for MyClass to derive indirectly from UIElement. If you ask your IDE to create it as a UserControl in a new file, it will probably generate some placeholder xaml for you as well.

hypehuman
  • 1,290
  • 2
  • 18
  • 37
  • Thank you hypehuman for your answer. I understand what you say but I am afraid my knowledge is not enough to allow me to implement your suggestion. It is odd also that if I move the method myCustomDisplay() inside the "public partial class MainWindow : Window" and I call it from there it works, but if I try and call it from a new method inside "class MyClass" it does not work again, despite the fact that the definition of myCustomDisplay() is now inside the "public partial class MainWindow : Window". I will update the question to be more clear. – Spyros Jun 07 '16 at 08:43