Mr. Orangutan.
Mr. Orangutan.

Reputation: 11

In WPF, how do I update the primary UI in a user control?

I have a problem.I want to update the main UI in a user control.I tried so many times, but i didn't make it.The test is divided into two categories as follows:

Class 1:

I first assigned the main window control (tbInfo, TextBlock type) directly, unsuccessfully. So I created a textBlockUpdate class (implementing the property change notification interface) and bind its properties (TextMessage) to the Text property of tbInfo,unsuccessfully. Then I used the content control,also unsuccessfully.The code as follows:

     //Feature code in user control.
 info = string.Format("Adding file{0}", System.IO.Path.GetFileName(FileName));
         if (_dataObject.MainWindow != null)
         {
                    _dataObject.MainWindow.ShowInfo(info);
         }


//Feature code in main window.
 public void ShowInfo(string info)
    {
        if (Dispatcher.CheckAccess())
        {
            //tbInfo.Text = info;
            //  textBlockUpdate.TextMessage = info;
            TextBlock textBlock = new TextBlock();
            textBlock.Text = info;
            tbInfoContainer.Content = textBlock;
        }
        else
        {
            Action<string> showInfoDel = (str) =>
            {
                //  tbInfo.Text = info;
                //textBlockUpdate.TextMessage = info;
                TextBlock textBlock = new TextBlock();
                textBlock.Text = info;
                tbInfoContainer.Content = textBlock;
            };
            Dispatcher.BeginInvoke(showInfoDel, info);
        }
    }

Class 2: I put the code in the user control into a thread, or did it not succeed.I tried three times, but I never succeeded.

1.

 new Thread(()=>{
            this.Dispatcher.Invoke(new Action(()=>{
                //Add the feature code above here
            }));
        }).Start();

2.

Application.Current.Dispatcher.Invoke(new Action(() => {
              //Add the feature code above here
        }));

3.

 Task task = new Task(()=> { 
   //Add the feature code above here
      });
                    task.Start();
                    task.Wait();

So, can anyone tell me How to do to make it work?

Upvotes: 1

Views: 1121

Answers (2)

Mr. Orangutan.
Mr. Orangutan.

Reputation: 11

I found a solution.Just change to the following method.

 //Call the render thread update UI from the current thread
                    int i = 1;
                    while (i < 10)
                    {
                        if (_dataObject.MainWindow != null)
                        {
                            _dataObject.MainWindow.ShowInfo(info);
                        }
                        Dispatcher.Invoke(new Action(() =>
                        {
                        }), System.Windows.Threading.DispatcherPriority.Background);
                       // Thread.Sleep(100);
                        i++;
                    }
                    //this is a time-consuming process.
                    accessObj.AddFile(_dataObject.Path, fileInfo, fileContent);
                    //Call the render thread update UI from the current thread
                    int j = 1;
                    while (j < 10)
                    {
                        if (j == 1) {
                            _dataObject.AttachFiles.Add(fileInfo);
                        }
                        Dispatcher.Invoke(new Action(() =>
                        {
                        }), System.Windows.Threading.DispatcherPriority.Background);
                        //Thread.Sleep(100);
                        j++;
                    }              

Upvotes: 0

BionicCode
BionicCode

Reputation: 28948

This is not how it is done. Also setting the properties of a class is not called binding. It's a simple assignment.

A Binding connects two or more (MultiBinding) properties (target and source) and updates them automatically, when one of the two changes.
To allow the binding to detect property changes, you have to implement the participating properties either as DependencyProperty (mandatory for binding target - preferable on controls) or let them raise the INotifyPropertyChanged.PropertyChanged event on property changes.

  1. Create the data and binding source

    MainWindow.xaml

    partial class MainWindow : Window
    {
      public static readonly DependencyProperty InfoProperty = DependencyProperty.Register(
        "Info",
        typeof(string),
        typeof(MainWindow),
        new PropertyMetadata(default(string)));
    
      public string Info
      {
        get => (string) GetValue(MainWindow.InfoProperty);
        set => SetValue(MainWindow.InfoProperty, value);
      }
    
      // Update the TextBlock via data binding
      public void ShowInfo(string info)
      {
        this.Info = info;
      }
    }
    
  2. Create the UI an set up the data binding

    MainWindow.xaml

    <Window>
      <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=MainWindow}, 
                                Path=Info}" />
    </Window>
    

See Microsoft Docs:

Data binding overview in WPF

How to: Implement a Dependency Property

Upvotes: 1

Related Questions