开发者

Edit ListBox on MainWindow from a class

I have a WPF application, i created a new class named Agent. On my WPF application window i have ListBox. I call Agent from the MainWIndow.xaml.cs .

Agent class runs a FileSystemWatcher and now when OnChanged event is raised i want to add the message to the ListBox that the event was raised.

MainWindow.xaml

<Window x:Class="MachineLogAgentGUI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Height="411" Width="515">
<Grid Background="#0A000000">
    <Button Content="Run Agent" Height="26" HorizontalAlignment="Left" Margin="397,12,0,0" Name="runAgent" VerticalAlignment="Top" Width="86" Click="runAgent_Click" />
    <ListBox Margin="12,66,12,12" Name="messageBox" />
    <TextBox Height="26" HorizontalAlignment="Left" Margin="12,12,0,0" Name="observedDirectory" VerticalAlignment="Top" Width="261" />
    <Button Content="Browse" Height="26" HorizontalAlignment="Left" Margin="271,12,0,0" Name="browse" VerticalAlignment="Top" Width="75" Click="browse_Click" />
    <CheckBox Content="Include Subfolders" Height="16" HorizontalAlignment="Left" Margin="12,44,0,0" Name="includeSubfolders" VerticalAlignment="Top" />
</Grid>

In MainWindow.xaml.cs i have:

    Agent agent = null;

    private void runAgent_Click(object sender, RoutedEventArgs e)
    {
        if (agent == null || !agent._running)
        {
            agent = new Agent(@"W:\MindWare.SVN\CardMax2\trunk\ProcessEngine\TSPHelper.Producer\bin\Debug\GeneratedLogs");
            runAgent.Content = "Stop Agent";
        }
        else if (agent._running)
        {
            agent.StopAgent();
            runAgent.Content = "Run Agent";
        }
    }

And Agent class:

public class Agent
{
    private string Path { get; set; }
    public bool _running { get; set; }

    FileSystemWatcher watcher = new FileSystemWatcher();

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public Agent(string path)
    {
        Path = path;
        watcher.Path = path;
        watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
           | NotifyFilters.FileName | NotifyFilters.DirectoryName;
        watcher.Filter = "*.txt";
        watcher.IncludeSubdirectories = true;

        watcher.Changed += new FileSystemEventHandler(OnChanged);

        watcher.EnableRaisingEvents = true;
        _running = true;
    }

    // Stop Agent
    public void StopAgent()
    {
        watcher.EnableRaisingEvents = false;
        _running = false;
    }

    // Define the event handlers.
    private void OnChanged(object source, FileSystemEventArgs e)
    {        
        try
        {
            watcher.EnableRaisingEvents = false;
            _running = false;

            // DO SOMETHING HERE
            // Add item to ListBox on MainWindow somehow
        }
        finally
      开发者_运维问答  {
            watcher.EnableRaisingEvents = true;
            _running = true;
        }
    }

How i could do that?


I think I understand what you mean.

You could create a static MainWindow object in the Agent class:

public class Agent
{
public static MainWindow mainWindow;

....
}

Then inside the MainWindow.cs you can add your window to the variable

private void Window_Loaded(object sender, RoutedEventArgs e)
{
  Agent.mainWindow = this;
  ....
}

Now when ever you need to access this you can reference mainWindow:

public class Agent
{
public static MainWindow mainWindow;

public void AddToList(string value)
{
   mainWindow.listBox1.items.add(value);
}

Edit: Update for Threading error

Sounds like the FileSystemWatcher runs on a seperate thread to the UI. you can manage this by getting passing the work to the UI thread

// DO SOMETHING HERE
// Add item to ListBox on MainWindow somehow
if (!mainWindow.Dispatcher.CheckAccess())
    {
       mainWindow.Dispatcher.BeginInvoke(
           System.Windows.Threading.DispatcherPriority.Normal,
           new Action(
              delegate()
              {
               //Code to make changes to the mainWindow if the thread does not have access:
                mainWindow.listBox1.Items.Add("hello");                                
              }));
    }
    else
    {
        //Access allowed make changes normally.
        mainWindow.listBox1.Items.Add("hello");
    }

Martyn


You probably should not do that since model-classes should be independent from the view.

Other than that why not pass a reference to the constructor of the class or exposing the ListView field as a public or internal property?


To expose your ListBox create a property like this:

public ListBox MessageBox { get { return messageBox; } }

This should be in your MainWindow code behind, then you can access the ListBox on any instance of the window via mainWindow.MessageBox.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜