I am searching for answer many hours and with no success. There is the way to do that, but every included element has to be static. What is not suitable for me.
I have MainPage class and Tile class. This tile class instantiates few kinds of tiles in MainPage layout. I need to add to some kinds of these tiles Tapped event. This event should modify MainPage elements.
What is the best way to do that? I always end with "non-static warning", as you can see in the code:
public class Tile
{
public static Grid buttonTile_MapPanel(int rowNum, int colNum)
{
Grid mapPanelButton = new Grid();
mapPanelButton.Background = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
TextBlock title = new TextBlock();
title.Text = "Mapa";
title.HorizontalAlignment = HorizontalAlignment.Center;
title.VerticalAlignment = VerticalAlignment.Center;
title.Foreground = new SolidColorBrush(Colors.White);
mapPanelButton.Children.Add(title);
//this will be signed as error: An object reference is required for non static field...
mapPanelButton.Tapped += new RoutedEventHandler(MainPage.mapPanelService);
return mapPanelButton;
}
}
public sealed partial class MainPage : Page
{
public void mapPanelService(object sender, RoutedEventArgs e)
{
MapPanel.Margin = new Thickness(0,0,0,0);
}
}
Main problem was bad type of handler, which demanded something else than it should.
Correct code:
public void dataPanelService(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
.
.
.
Related
I'm trying to add a Label to a Windows Form by using another class programmatically. My Label does not appear inside the Form.
I don't know where I'm going wrong.
private void Form1_Load(object sender, EventArgs e)
{
Ticker ticker = new Ticker("ASDF");
ticker.display();
}
public class Ticker : Label
{
string labelText;
Label label = new Label();
public Ticker(string _labelText)
{
labelText = _labelText;
}
public void display()
{
label.Text = labelText;
Controls.Add(label);
}
}
You can make a few changes to your Ticker Custom Control:
You don't need to create a new Label inside your Custom Control: your Control is already a Label, use the this reference to set its properties (see also this keyword (C# Reference)).
The Text is the current Label's Text (this.Text). Store it if you need a copy of it for other reasons (custom painting, usually, so sometimes you need to clear the Text).
Controls is referring to the current class object: it's a Control, so it has a Controls property, which gets the ControlCollection of the child Controls of a Control.
You need to also specify a Point that defines the position of your Custom Control inside its Parent's ClientRectangle.
Even if it's not always required, add a parameter-less Constructor to your Custom Control: if/when it's actually needed, you'll have it already there.
If you don't want to set the Parent Control from the outside, as usual (e.g., var label = new Label(); this.Controls.Add(label);), you need to pass the reference of the Control which will become the Parent Control of your custom Label.
You can the use this reference - a Control type of reference - and add your Label to the Controls collection of the Control reference you receive:
// You want to store a reference to this Control if you need it later...
private Ticker ticker = null;
private void Form1_Load(object sender, EventArgs e)
{
//... or just declare it with: var ticker = new Ticker() if you don't
ticker = new Ticker("The Label's Text");
// [this] of course refers the current class object, Form1
ticker.Display(this, new Point(100, 100));
// Or, display the Label inside a Panel, child of Form1
// Note: if you don't comment the next line, the Label will be moved to panel1
ticker.Display(this.panel1, new Point(10, 50));
}
Here, I'm overloading the Display() method, so it accepts both a Parent reference and a Point value, used to position the Control inside its Parent's Client Area.
The Custom Label also calls BringToFront() on itself, to avoid showing up under some other, already existing, child Control of the new Parent.
public class Ticker : Label
{
public Ticker() : this("ticker") { }
public Ticker(string labelText) => this.Text = labelText;
public void Display(Control parent) => Display(parent, Point.Empty);
public void Display(Control parent, Point position)
{
this.Location = position;
parent.Controls.Add(this);
this.BringToFront();
}
}
I'm trying to generate a very simple PDF just for practice by using SimpleWPFReporting.
Since there is no sample code in its documentation, I tried creating a sample from what I understood:
Window1.xaml.cs
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
public class Sample
{
private string _aw;
public string Aw
{
get { return _aw; }
set { _aw = value; }
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
StackPanel stkMain = new StackPanel();
stkMain.Background = Brushes.Pink;
stkMain.Height = 100;
stkMain.Width = 100;
TextBlock txtSample = new TextBlock();
txtSample.Text = "SAMPLE TEXT";
stkMain.Children.Add(txtSample);
ReportOrientation portrait = ReportOrientation.Portrait;
Sample sample = new Sample()
{
Aw = "Some text"
};
Report.ExportReportAsPdf(stkMain, sample, portrait);
}
}
It does save as a PDF, but when I open it, it's blank. What I'm expecting is to see at least the TextBlock there.
I don't really understand the use of data context in the arguments, so I just added a class there. I tried looking for tutorials but failed. Did I miss something or did I create it wrong?
I believe you have to specify the stackpanel orientation as "vertical", as stated in the doc
https://github.com/maximcus/SimpleWPFReporting
After digging in to the source code, it uses a Visual,so you have to add the stackpanel to the visual tree in order to be renderer and then printed.
You can create a previewer window, add the stackpanel and now the pdf will show the content.
I will create a previewer by myself, so I will post when I finish it.
So I am developing a custom ButtonGUI class for my game. Here's the initialization of the button object:
// Button code:
ButtonGUI btn1 = new ButtonGUI("Button 1", new Rectangle(150, 300, (int)myFont.MeasureString(menuButtons[0]).X, (int)myFont.MeasureString(menuButtons[0]).Y), myFont, Color.CornflowerBlue);
Now consider this code:
// Draw() method:
btn1.Draw(spriteBatch);
if (btnHover)
{
btn1.btnRect = new Rectangle(140, 300, (int)hoverFont.MeasureString(menuButtons[0]).X, (int)hoverFont.MeasureString(menuButtons[0]).Y);
btn1.btnFont = hoverFont;
btn1.btnColour = Color.Red;
}
else
{
btn1.btnRect = new Rectangle(150, 300, (int)myFont.MeasureString(menuButtons[0]).X, (int)myFont.MeasureString(menuButtons[0]).Y);
btn1.btnFont = myFont;
btn1.btnColour = Color.CornflowerBlue;
}
This would be OK if I had only 1 button... But if I have like 10 buttons or more? This really isn't what DRY suggests. I feel like I'm missing something, there must be a way to return button properties to their default values once the condition is no longer met without doing the whole thing manually, or is there? Thanks in advance!
It may make sense to create a structure to hold all of the values that may change.
class ButtonData
{
// put members corresponding to each member of ButtonGUI you wish
// to change
}
class ButtonSwapper
{
ButtonGUI myButton;
ButtonData hoverData;
ButtonData notHoverData;
void change(bool hover)
{
ButtonData dataToUse = hover ? hoverData : notHoverData;
// set each relevant member of myButton to its pair in
// dataToUse
}
}
then call change as necessary.
I learn how to do this based on this tutorial : http://www.nbdtech.com/Blog/archive/2009/04/20/wpf-printing-part-2-the-fixed-document.aspx
This is the method that my Print Button fired when clicked :
PrintManager _pm;
private void btnPrint_Click(object sender, RoutedEventArgs e)
{
_pm = new PrintManager();
List<Canvas> pages = new List<Canvas>();
pages.Add(cnv);
_pm.Print(pages);
}
And this is my PrintManager.cs (_pm) :
private const double PAGE_WIDTH = 793.92; //8.27' * 96px
private const double PAGE_HEIGHT = 1122.24; //11.69' * 96px
private FixedDocument _document;
private List<FixedPage> _listOfPages;
private PageContent _tempPageContent;
private FixedPage _tempPage;
public PrintManager()
{
}
public void Print(List<Canvas> pages)
{
PrintDialog pd = new PrintDialog();
Canvas temp;
if (pd.ShowDialog() == true)
{
_document = new FixedDocument();
_document.DocumentPaginator.PageSize = new System.Windows.Size(PAGE_WIDTH, PAGE_HEIGHT);
_listOfPages = new List<FixedPage>();
for (int i = 0; i < pages.Count; i++)
{
_listOfPages.Add(new FixedPage());
_tempPage = _listOfPages[_listOfPages.Count - 1];
_tempPage.Width = PAGE_WIDTH;
_tempPage.Height = PAGE_HEIGHT;
_tempPage.Children.Add(pages[i]); //THIS IS THE PROBLEM LINE
_tempPageContent = new PageContent();
((IAddChild)_tempPageContent).AddChild(_tempPage);
_document.Pages.Add(_tempPageContent);
}
pd.PrintDocument(_document.DocumentPaginator, "Docdoc");
}
}
It turns out that there's an error from the problem line (_tempPage.Children.Add(pages[i]);) line which says :
Specified element is already the logical child of another element. Disconnect it first.
Any idea why?
Even removing the element from private List<FixedPage> _listOfPages; before it's added into the page list didn't help (of course I tried it outside the for loop) with just 1 canvas in the list.
P.S. I need it to be multi-page-able, since my document is usually long (it's a musical scores).
P.S.S. Even printing a canvas with no children manually added, the error was still the same.
P.S.S.S. Another simpler algorithm, even if it's different, is acceptable.
Thanks.
It seems that I need to "copy" the canvas content into a new canvas class before sending it to printer.
And clear it from the old canvas. Is anyone can do it better?
Context: I am trying to make a little game of Backgammon in Windows.Forms. I have 3 classes GameBoard.cs, Points.cs and Checkers.cs (as well as Form1.cs). What I need to be able to do is change values of some properties of a PictureBox using some of my other classes.
Specifically I have this code:
// gameBoard.cs
namespace backgammon
{
public class gameBoard
{
Checker checker1;
Points point1;
Points[] pointsArray;
public gameBoard()
{
// make new checker (ID, PictureBox, startingPoint)
checker1 = new Checker(1, checkerPicBox1, 1);
// make new Point (ID, arrayOfCheckers)
point13 = new Points(1, new Checker[]{checker1 /*,checker2... etc*/});
pointsArray = new Points[MAX_POINTS];
pointsArray[0] = point1;
}
}
}
so this is how I have "setup" the checkers and points. My checker and point classes can get and set on all variables that were passed into its construction.
Problem: what I am trying to achieve is to "highlight" a checker once it is clicked.
In Form1:
// Form1.cs
private void checkerPicBox1_Click(object sender, EventArgs e)
{
int pointNumber = gameBoard.checker1.getPointMember();
// find the top most checker in the checker array so we can highlight it
Checker topMost = gameBoard.pointsArray[pointNumber - 1].getCheckerFromIndex(gameBoard.pointsArray[pointNumber - 1].getCheckerArray().Length - 1);
// get the picturebox and change the image
topMost.getPictureBox().BackgroundImage = global::Backgammon.Properties.Resources.blackCheckerSelected;
}
The code compiles and runs but when it gets to the last line of checkerPicBox_Click nothing seems to happen (the image doesn't change).
What is happening here? Do I not have the correct instance of my PictureBox? Or am I doing this in a weird way/not the way i'm supposed to be?
Since the checkers are connected to the pictureboxes, why not create a new reference property for them in the Checker class?
You could pass the form containing the pictureboxes in the constructor, and use the form to create your references to the right picturebox instances.
// gameBoard.cs
namespace backgammon
{
public class gameBoard
{
Checker checker1;
Points point1;
Points[] pointsArray;
public gameBoard(Form gameForm)
{
// make new checker (ID, PictureBox, startingPoint)
checker1 = new Checker(1, gameForm.checkerPicBox1, 1);
// make new Point (ID, arrayOfCheckers)
point13 = new Points(1, new Checker[]{checker1 /*,checker2... etc*/});
pointsArray = new Points[MAX_POINTS];
pointsArray[0] = point1;
}
}
}
Add the picturebox property to your Checker class:
// checker.cs
public class Checker
{
PictureBox _picturebox;
//... other code here
public Checker(int ID, PictureBox picturebox, Points startingPoint)
{
_picturebox = picturebox;
//...other code here
}
}
Then we can use this in the game form:
gameBoard gameBoard1 = new gameBoard(this);
gameBoard1.checker1._picturebox.BackgroundImage = global::Backgammon.Properties.Resources.blackCheckerSelected;
gameBoard1.checker1._picturebox.Invalidate();