C # WPF / XAML доступ к TextBox из любого места / любой поток помощь - PullRequest
2 голосов
/ 17 марта 2011

Я пытаюсь опубликовать текстовое поле в любом месте моей программы, независимо от того, в каком потоке он находится, и какому объекту он принадлежит и т. Д.

Ниже я попробовал несколько вещей, всене сработает

Попытка 1: tbLog не существует в Очистке, и другой поток владеет им.

namespace MyProgram 
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Cleaning clng = new Cleaning(); 
        }

        public buttonStartTasks_Click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                Dispatcher.Invoke(new Action(delegate { tbLog.Text += "Starting to clean"; }));
                clng.cleanRoom(); 
            }

            worker.RunWorkerAsync();
        }
    }
}

namespace Tasks
{
    public class Cleaning
    {
        public void cleanRoom()
        {
            tbLog.Text += "Dusting...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Sweeping...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Hanging up clothes...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Organize shelves...."; 
            Thread.Sleep(50000); //work sim
            tbLog.Text += "Remaining odds and ends...."; 
            Thread.Sleep(50000); //work sim
        }
    }
}

Попытка 2: Я попытался передать tbLog в Очистку.Я получил эту ошибку «Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет им».Что имеет смысл.

namespace MyProgram 
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Cleaning clng = new Cleaning(tbLog); 
        }

        public buttonStartTasks_Click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                Dispatcher.Invoke(new Action(delegate { tbLog.Text += "!!! Starting to clean !!!"; }));
                clng.cleanRoom(); 
            }

            worker.RunWorkerAsync();
        }
    }
}

namespace Tasks
{
    public class Cleaning
    {

        private TextBox LOG { get; set; }

        public Cleaning(TextBox log)
        {
            this.LOG = log; 
        } 

        public void cleanRoom()
        {
            LOG.Text += "Dusting...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Sweeping...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Hanging up clothes...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Organize shelves...."; 
            Thread.Sleep(50000); //work sim
            LOG.Text += "Remaining odds and ends...."; 
            Thread.Sleep(50000); //work sim
        }
    }
}

Попытка 3: Я попытался использовать Dispatcher в Очистке и получил ошибку компиляции, сообщающую, что его не существует.Так что теперь я застрял.Я не знаю, что еще попробовать.Я гуглил кучу, но это всегда сводится к ошибке владения потоком.

if (Dispatcher.Thread != Thread.CurrentThread)
{
    Dispatcher.Invoke(new Action(delegate { this.LOG.Text += "No clean for you!"; }));
}
else
{
    this.LOG.Text += "No clean for you!";
}

TextBox для всех:

<TextBox Name="tbLog"
    Height="200" 
    Width="200"
    HorizontalAlignment="Left" 
    VerticalAlignment="Top"  
    VerticalScrollBarVisibility="Visible" 
    IsReadOnly="True" />  

Спасибо за любую помощь!

Ответы [ 4 ]

4 голосов
/ 17 марта 2011

Вчера я просто возился с этим, пытаясь постепенно загрузить ListBox из другого потока. Я заставил его работать, изменив Dispatcher.Invoke () на Application.Current.Dispatcher.Invoke ().

0 голосов
/ 18 марта 2011
0 голосов
/ 17 марта 2011

Я бы сказал, что наилучшим способом было бы связать свойство text вашего текстового поля со свойством зависимостей и обновить свойство зависимостей от вашего фонового работника. Чтобы значение текстового поля обновлялось из потока, вам необходимо реализовать INotifyPropertyChanged.

0 голосов
/ 17 марта 2011

Это потому, что вы не можете просто выполнять действия над элементами управления из других потоков, кроме основного потока пользовательского интерфейса.Если вы хотите сделать это, вы должны использовать Invoke или BeginInvoke из Dispatcher.

Введение к этому можно найти здесь , там вы также найдете примеры кода, которые помогут вам решить эту проблему.

...