0

I have a Windows Tray project that opens a WPF window when Settings is clicked. The WPF window opens and displays some of the content properly, but I have two lists that are bound to another class that have odd behavior.

These lists are displayed on two different tabs as devices. On one tab, there is a graphical representation from which the device can be started, and the other tab shows the settings for the device. Everything works perfectly when the WPF application is set as the startup project. However, when I start it from the tray, the lists load correctly, and display in the first tab, where they can be started, but the second tab shows no devices present. They are both linked to the same data.

At first, I thought that there was an issue with binding, but after several days of trying to resolve this, I believe the problem is with App.xaml, where there is a reference to a resource. I suspect that since i am not referencing App.xaml, the resource is not loaded, and the list is not being set up properly. The only difference between the project working and not working is that one has the WPF as startup project, and the other uses the tray to call the WPF.

My question, then, is how do I reference App.xaml to ensure that I load the required resource.

Below is some of my code, in case it might help.

App.xaml

<Application x:Class="Sender_Receiver.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Shell.xaml">
<Application.Resources>
    <ResourceDictionary Source="Themes\Generic.xaml"/>
</Application.Resources>

Current call to open the WPF

        private void settingsEvent_Click(object sender, EventArgs e)
    {
        gui = new Sender_Receiver.mainWindow(); // mainWindow() located in Shell.xaml
        gui.Show();
    }

Code to display the devices. A collapsibleSection implements Expander and RepeatControl implements ItemsControl.

<c:CollapsibleSection Header="Senders">
        <c:CollapsibleSection.CollapsedContent>
            <c:RepeatControl Margin="30,0,0,0" ItemsSource="{Binding SendersList}"  
                              ItemType="{x:Type m:Sender}"  List="{Binding SendersList}"  
                              ItemTemplate="{StaticResource SenderSummary}"/>
        </c:CollapsibleSection.CollapsedContent>
        <Border BorderThickness="1" BorderBrush="Chocolate" Margin="30,0,0,0">
            <c:RepeatControl  ItemsSource="{Binding SendersList}"  
                                  ItemType="{x:Type m:Sender}" 
                                  List="{Binding SendersList}"  
                                  ItemTemplate="{StaticResource SenderTemplate}"/>
        </Border>
    </c:CollapsibleSection>

The image below shows how the application is behaving under different conditions.

WPF does not display all data when called from the Tray.

Any assistance would be greatly appreciated.

Tim
  • 2,731
  • 9
  • 35
  • 72

1 Answers1

0

I finally figured this one out. Instead of instantiating the UI, the entire WPF application must be called to run. This will cause the App.xaml to load the dictionary, and other WPF forms can then access it. This is done with the following code:

private void settingsEvent_Click(object sender, EventArgs e)
    {
        if (gui == null)
        {
            gui = new App();
            gui.MainWindow = new mainWindow();
            gui.InitializeComponent();
        }
        else
        {
            gui.InitializeComponent();
            gui.MainWindow.Show();
            gui.MainWindow = new mainWindow();
        }
    }
    private static App app = new App();

You must keep adding the mainWindow back to the App, as it seems to be set to null when the window shows.

This was discovered through experimentation, so i am sure it is not the best practice, but it works, and right now, that was what I needed.

EDIT

For my purposes, however, this still was not working. I could either open the Settings window only once, or I could not get an event handler to work on it the first time it was open. Finally, Josh came up with the correct answer:

Process myProcess = new Process();
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.FileName = "C:\\mysettingsapp\\mysettingsapp.exe"; // replace with path to your settings app
myProcess.StartInfo.CreateNoWindow = false;
myProcess.Start();
// the process is started, now wait for it to finish
myProcess.WaitForExit();  // use WaitForExit(int) to establish a timeout

His full explanation can be found here.

Community
  • 1
  • 1
Tim
  • 2,731
  • 9
  • 35
  • 72