Как обновить окно вместо создания нового в wpf
У меня есть программа с моим MainWindow и моим Window1. У меня есть несколько кнопок и несколько меток в MainWindow, когда я нажимаю одну, он открывает Window1 (все эти кнопки открывают одно и то же Window1, но с другим содержимым в зависимости от кнопки, которую я нажимаю). Затем в Window1 у меня есть текстовое поле и кнопка, когда я нажимаю кнопку, она должна заполнять одну из меток в MainWindow, и это происходит, проблема в том, что при попытке заполнить другую метку он удаляет предыдущие метки, которые я заполнил .
Мой полный проект немного отличается, но больше. Извините, если вы меня не поняли, я не говорю по-английски.
2 ответа
Как было сказано ранее, вы создаете новое окно MainWindow, которое отменяет все ваши предыдущие изменения. Попробуйте назначить MainWindow владельцем Window1, чтобы вы могли ссылаться на исходное окно Window.
Примерно так:
MainWindow:
Поскольку вы воссоздаете MainWindow. Каждый раз, когда вы открываете новое окно, вы создаете новый экземпляр MainWindow в этом классе, поэтому старое текстовое поле очищается.
Как обновить окно wpf c
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
![]()
- ProfileText
- Sign in
Answered by:
Question
I am looking for a solution for refreshing the GUI in a WPF application which is running in a loop that writes information to the GUI (let’s say into a Label):
for (int i = 0; i < 100; i++)
<
this.lblInfo.Content = i.ToString();
// How to refereh the GUI?
>
In Windows.Forms one can use the Refresh method of the updated control or Application.DoEvents.
I know that I can run the code in an thread to ensure GUI updating (i.e. using the BackgroundWorker). Is this the only way to ge an responding GUI in WPF?
Thanks in advance
Answers
This works and was found on some other blog.
public static class ExtensionMethods
private static Action EmptyDelegate = delegate () < >;
public static void Refresh( this UIElement uiElement)
private void LoopingMethod()
- Marked as answer by Jürgen Bayer Friday, September 3, 2010 9:07 PM
You can use the InvalidateVisual method on the element or parent element.
Using a worker thread is probably the best way, but if you want another option you can take a look here — seems that you can update the UI using the Dispatcher .PushFrame() API. Unfortunetly nobody seems to know how safe is this method.
Another idea is to use the OnIdle() function and do one iteration per call. OnIdle() is called when no Windows messages are being processed . Here is a little sample:
void Init()
<
ComponentDispatcher.ThreadIdle += new EventHandler(OnIdle);
int i = 0;
>
private void OnIdle(object sender, EventArgs e)
<
if(i == 100)
<
// stop processing OnIdle()
ComponentDispatcher.ThreadIdle -= OnIdle;
>
else
<
// do iteration
this.lblInfo.Content = i.ToString();
i++;
>
>
All replies
You can use the InvalidateVisual method on the element or parent element.
Using a worker thread is probably the best way, but if you want another option you can take a look here — seems that you can update the UI using the Dispatcher .PushFrame() API. Unfortunetly nobody seems to know how safe is this method.
Another idea is to use the OnIdle() function and do one iteration per call. OnIdle() is called when no Windows messages are being processed . Here is a little sample:
void Init()
<
ComponentDispatcher.ThreadIdle += new EventHandler(OnIdle);
int i = 0;
>
private void OnIdle(object sender, EventArgs e)
<
if(i == 100)
<
// stop processing OnIdle()
ComponentDispatcher.ThreadIdle -= OnIdle;
>
else
<
// do iteration
this.lblInfo.Content = i.ToString();
i++;
>
>
Thanks for your answer.
InvalidateVisual is not what I was looking for. As documented it only invalidates the part of the GUI which contains the element. This does not cause a refresh since the program is running in a loop which gives Windows no time to repaint the GUI. It seems that WPF does not have an equivalent to the Refresh method of Windows.Forms controls.
The idea behind is to create a thread that will do a beginInvoke back to the ui thread. The main advantage is that inline delegates allow doing all these changes inside only one function.
Agreed, anonymous delegates are really really nice for wiring up activity to any event. You can add them immediately at the click event like this.
button_buttonName.Click += delegate(object obj, EventArgs e)<
//do something here
But what I don’t understand is that in 2008 Express edition when you create a WPF application. A shell "Window" pops up with nothing in it. Now lets say I want to create XAML expressions that change color or size but I want the code behind to do it in a iterative loop. In the past, on a Forms application one just simply made the change desired (in the loop) and called the ubiquitous Control.Refresh() method. What is the equivalent in a WPF "Window" where buttons and rectangles et. al. are contained in the "Window"? I don’t understand why this would be omitted? How can you refresh XAML controls from Code behind?
Also, is WPF more of a browser solution or just a new form or Windows forms? It seems to by a hybrid browser type solution in a Windows frame, but it doesn’t have the characteristics of a Windows Form and it doesn’t have the characteristics of a WebBrowser.
P.S. Can XAML be utilized in a Windows Form?
I am looking for a solution for refreshing the GUI in a WPF application which is running in a loop that writes information to the GUI (let’s say into a Label):
for (int i = 0; i < 100; i++)
<
this.lblInfo.Content = i.ToString();
// How to refereh the GUI?
>
In Windows.Forms one can use the Refresh method of the updated control or Application.DoEvents.
I know that I can run the code in an thread to ensure GUI updating (i.e. using the BackgroundWorker). Is this the only way to ge an responding GUI in WPF?
Thanks in advance
If you change Label.Content UI will update. Just run you code in VS and watch the numbers increment (I’d recommend to insert Thread.Sleep).
Keep in mind: If you call this on UI thread you will just block it and UI will have no chance to udate itself unless you code returns. So call it on other thread (for example on ThreadPool. QueueUserWorkItem) and update UI through Dispatcher. For example like this:
for ( int i = 0; i < 100; i++)
this .Dispatcher.BeginInvoke( new Action (() => this .label.Content = i.ToString()), null );
Hope this helps. Sorry about that fancy lambda thing. I like it 🙂
PS. IMHO WPF is about getting rid of the stuff like this where you directly manipulate element properties. It’s about databinding. I think so.
Yes, but I didn’t see it as a clear answer. let me try your suggestion and thanks.
| for ( int i = 0;i<100;i++)< |
| System.Threading.Thread.Sleep(200); |
| this .Dispatcher.BeginInvoke( new Action(() => rectangle2.Width = ( double )i), null ); |
| > |
This did not work. the new value showed up only after the loop was completed. The refresh only happened once this event was done.
This works and was found on some other blog.
public static class ExtensionMethods
private static Action EmptyDelegate = delegate () < >;
public static void Refresh( this UIElement uiElement)
private void LoopingMethod()
- Marked as answer by Jürgen Bayer Friday, September 3, 2010 9:07 PM
The good news about a worker thread is its ability to keep the Interface Thread open for input. The worker can report its progress back to the Interface layer through its thread relationship. However its not always the best course of action, in theroy a worker should be used when processing data and displaying changes to the interface. However when that change occurs far to frequently the worker process runs into issues with the WPF Queue’s (I’m assuming for the sake of this argument that the interface control layer is a fine system of queue’s.).
WPF attempts to prevent the interface from rendering itself if another render action is "inQueue" (or about to be performed). It tries (in a certain number of milliseconds) to wait for all the rendering changes to be made. For instance when you are scrolling through a database and adding an object for qualifying rows the WPF Interface Layer will wait for all objects to be added. This becomes a pain. In traditional windows forms the programmer could force a redraw of the screen to let the user know something is happening. In WPF the safest way is to send Interface requests from a worker which if the process is sending interface commands to fast (as compared by the CPU power and speed. etc.) the items will not render till the end of the operation. Only the last set of non-conflicting interface actions will be performed. For instances changing a label text 3 times during the process will only display the 3rd and last change.
I like the idea of pushing a frame out to the dispatcher. Of course you might run into issues if you perform the dispatcher to frequently, or if you have pending high level interface changes (such as a drop of an object). The other solution of creating the "Refresh()" extension for WPF does help. In best practice, refrsh the object your changing and refrsh its owner. This gives WPF enough time to "breathe" and allow the interface changes to be rendered.
Rendering is, and has always been, a computer intensive operation. Your talking about mathematical calculations that you’re better off leaving to the operating system. Of course WPF (as to prevent the issues with its predecessors) will try to lower the amount of rendering actions being performed during a processes life cycle. Your better off telling WPF to push the actions out to the screen from the worker, refesh method, or better yet (if someone could verify how safe the action is to the threads) push out the frame to the dispatcher. WPF was designed to utilize a very interesting time line of events. Pushing the frame out to the dispatcher is probably a good place to start.
Как обновить окно в wpf?
У меня есть небольшой проект, над которым я работаю, — это окно с 4 вкладками WPF на нем.
Первая вкладка — это то, где я выполняю большую часть работы, но иногда мне нужно вернуться на другие вкладки. На одной из этих вкладок есть DataGrid, привязанный к списку, на который влияет основная вкладка, на которой я остаюсь.
Когда я обновляю что-то на первой вкладке, мне это нужно, чтобы вызвать обновление данных в Datagrid (обычно просто для обновления значения).
Единственный способ, которым он работал, — это если я сам нажму на заголовок.
Обновление окна WPF
Начал разбираться в WPF, и сразу столкнулся с такой проблемой: в коде есть переменная, которую я постоянно меняю. Она отображается в форме в Label. Но при изменении ее в коде в форме она не меняется. Как это вообще реализуется? У меня эта переменная изменяется в отдельном фоновом потоке, и нужно, чтобы на экране она тоже обновлялась.
Ответы (1 шт):
Для начала, вам нужно, чтобы переменная, которую вы отображаете на экране, была частью DataContext . Например, вы кладёте её в класс, и присваиваете DataContext ‘у его экземпляр:
Теперь можно привязаться к вашему свойству:
Но это не всё. Для того, чтобы окно увидело изменения переменной, вы должны реализовать интерфейс INotifyPropertyChanged :
Но и это ещё не всё. Теперь чтобы всё работало правильно, вам нужно устанавливать значение VM-свойства только в главном потоке. Как это делать — зависит от выбранных вами инструментальных средств. Например, вы можете использовать BeginInvoke в вашем рабочем потоке. Или выполнять вычисления в фоне при помощи техники async/await.