Search code examples
c#mvvmwindows-phone-8uielement

Add programmatically UIElement to the View in a asynchronous way


I'm actually trying to add in a asynchronous way some UIElement to my Canvas define in my MainPage.

As I understand the basic way to add UIElement to a Canvas is to add it on his UIElementCollection, for example with a Line I should do like that:

        Line line = new Line();

        // Line attributes
        line.Stroke = new SolidColorBrush(Colors.Purple);
        line.StrokeThickness = 15;
        Point point1 = new Point();
        point1.X = 0;
        point1.Y = 0;
        Point point2 = new Point();
        point2.X = 480;
        point2.Y = 720;
        line.X1 = point1.X;
        line.Y1 = point1.Y;
        line.X2 = point2.X;
        line.Y2 = point2.Y;
        // Line attributes

        MyCanvas.Children.Add(line);

Let's imagine that I have a Class call Graphics that needs to access this Canvas in order to draw on it.

 public class Graphics
 {
     public void drawLine()
     {
            //Using Dispatcher in order to access the main UI thread
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
               Line line = new Line();

               // Line attributes

               /**
                *  Here I want to access the Canvas of the MainPage
                *  I have no Idea what to put here !!!
                *
                **/

            });
      }
  }

In the place "I have no Idea what to put here !!!" I tried to access directly to the MainPage Canvas --> FAIL

I tried to declare a public static UIElementCollection in the MainPage in order ta add my UIElement then pass it to the Canvas but not possible because UIElementCollection has no constructor --> FAIL

But those ideas seems to be dirty coding and not really elegant. So through my research I see that MVVM should do the magic. But all the tutorial I found were doing the data-biding through the xaml file which can't be use in my case.

So I have 2 questions:

First: How is use the UIElementCollection of the Canvas? (is there a hidden method called who draws it, like Paint or Repaint in JAVA?)

Second: If I want to follow the MVVM pattern can I consider the MainPage as my View, the Graphics class as my ViewModel and the UIElement as my Model?


Solution

  • This is a really basic example but should get you going in the correct direction.

    Graphics.cs

     public class Graphics
    {
        public ObservableCollection<UIElement> UIElements { get; set; }
        int poisiton = 0;
        private Timer backgroundTimer;
        public Graphics()
        {
            this.UIElements = new ObservableCollection<UIElement>();
            this.backgroundTimer = new Timer(new TimerCallback((timer) => {
                Deployment.Current.Dispatcher.BeginInvoke(() => this.GenerateLine());
            }), null, 2000, 3000);
        }
    
        private void GenerateLine()
        {
            Line line = new Line();
    
            // Line attributes
            line.Stroke = new SolidColorBrush(Colors.Purple);
            line.StrokeThickness = 15;
            Point point1 = new Point();
            point1.X = this.poisiton;
            point1.Y = this.poisiton;
            Point point2 = new Point();
            point2.X = this.poisiton;
            point2.Y = this.poisiton + 30;
            line.X1 = point1.X;
            line.Y1 = point1.Y;
            line.X2 = point2.X;
            line.Y2 = point2.Y;
            // Line attributes
    
            this.poisiton += 10;
            UIElements.Add(line);
        }
    }
    

    MainPage.xaml.cs

     public MainPage()
     {
          InitializeComponent();
    
          this.Loaded += MainPage_Loaded;
          // Sample code to localize the ApplicationBar
          //BuildLocalizedApplicationBar();
     }
    
      void MainPage_Loaded(object sender, RoutedEventArgs e)
      {
          var graphics = new Graphics();
          this.ContentPanel.DataContext = graphics;
      }
    

    MainPage.xaml

      <Canvas x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
          <ItemsControl ItemsSource="{Binding UIElements}">
    
          </ItemsControl>
      </Canvas>
    

    I hope this helps.