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?
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.