How to connect a custom propertyGrid with a standard control in C#? - c#

I am creating a graphing program and I would like to allow the user to be able to change the look of the graph they create. Providing them with the opportunity to change the series color, data point size, ect. I am allowing them to do this through the use of a propertyGrid. Through the help of the wonderful people who use stack overflow I was able to import all the properties of a chart into my property grid, however; Now I can't figure out how to connect my chart to the propertyGrid, so when I change something in the grid the chart changes.
So far I have
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
magRadioBox.Checked = true;
PropertyGrid propertyGrid1 = new PropertyGrid();
propertyGrid1.CommandsVisibleIfAvailable = true;
propertyGrid1.Text = "Graph and Plotting Options";
propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
this.Controls.Add(propertyGrid1);
}
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "MY Plot Program";
propertyGrid1.SelectedObject = chart1;
}
private void button1_Click(object sender, EventArgs e)
{
//some code that is populating my chart(chart1) with data
//....chart1 being filled with data
}
private void propertyGrid1_PropertyValueChanged(object s , PropertyValueChangedEventArgs e)
{
//Getting the MyChart instance from propertyGrid
MyChart myChart = (MyChart)(((PropertyGrid)s.SelectedObject);
//Calling the method that will refresh my chart1
myChart.Invalidate();
}
The above code is for my Form. The my "MyChart" class code is
namespace FFT_Plotter
{
[DefaultPropertyAttribute("Text")]
public class MyChart : Chart
{
public event EventHandler PropertyChanged;
private void OnPropertyChanged(object sender, EventArgs e)
{
EventHandler eh = propertyChanged;
if(eh !=null)
{
eh(sender, e);
}
[BrowsableAttribute(false)]
public new System.Drawing.Color BackColor
{
get { return BackColor; }//Here back color is just an example of a property, not necessarily one that I would make non-Browsable
set
{
base.BackColor = value;
OnPropertyChanged(this,EventArgs.Empty);
}
}
}
}
The class above gets me so far as having a property grid that has all the properties of a chart and allows me to hide those properties as I see fit. However now I am stuck in understanding how to connect my chart1 to the grid I've created. If anyone has any advice on how to do that, it would be incredibly helpful.

You have to add propertyGrid1.SelectedObject = myChartInstance;, then you have to add PropertyValueChanged event listener that will be triggered each time a user changes myChartInstance property via PropertyGrid. So, assuming that you want to redraw the chart each time the change has been done, the code should look like this:
private void propertyGrid1_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
{
// Redraw the chart.
chart1.Invalidate();
}
public Form1()
{
InitializeComponent();
magRadioBox.Checked = true;
PropertyGrid propertyGrid1 = new PropertyGrid();
propertyGrid1.CommandsVisibleIfAvailable = true;
propertyGrid1.Text = "Graph and Plotting Options";
// Create your chart.
chart1 = new MyChart();
// Attach your chart to Property Grid.
propertyGrid1.SelectedObject = (MyChart) chart1;
propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
this.Controls.Add(propertyGrid1);
}

Through the help of the great community on StackOverflow this was the answer I was able to piece together, (standing on the shoulders of giants)
public partial class Form1 : Form {
public Form1()
{
InitializeComponent();
magRadioBox.Checked = true;
PropertyGrid propertyGrid1 = new PropertyGrid();
propertyGrid1.CommandsVisibleIfAvailable = true;
propertyGrid1.Text = "Graph and Plotting Options";
propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
this.Controls.Add(propertyGrid1);
} private void Form1_Load(object sender, EventArgs e) { this.Text = "MY Plot Program"; propertyGrid1.SelectedObject = chart1; }
private void button1_Click(object sender, EventArgs e) {//some code that is populating my chart(chart1) with data .... //chart1 being filled with data }
private void propertyGrid1_PropertyValueChanged(object s , PropertyValueChangedEventArgs e) {
myChart.Invalidate();
}
This is the code for the MyChart class
namespace FFT_Plotter
{
[DefaultPropertyAttribute("Text")]// This is where the initial position of the grid is set
public class MyChart : Chart
{
public event EventHandler PropertyChanged;
private void OnPropertyChanged(object sender, EventArgs e)
{
EventHandler eh = propertyChanged;
if(eh !=null)
{
eh(sender, e);
}
[BrowsableAttribute(false)]
public new System.Drawing.Color BackColor
{
get { return BackColor; }//Here back color is just an example of a property, not necessarily one that I would make non-Browsable
set {
base.BackColor = value;
OnPropertyChanged(this,EventArgs.Empty);
}
}
}
}
And this declares chart1 to be a MyChart rather than System.Windows...Chart, in the Form1.Designer.CS
...this.chart1 = new FFT_Ploter.MyChart(); ... private FFT_Plotter.MyChart chart1;

Related

winforms: move a borderless form (without title bar)

I have a host class which inherits from Form. I use it to embed an WPF user control to use it in a winform application. This is customizable, I mean, you can choose to make form borderless or not.
If borderless, you cannot move the window, so I need to implement it manually. In this case I subscribe to some event which do the trick (I have removed the not necessary things from the class to focus only on the important parts):
public class MyHostDialog : Form
{
public MyDialogHost()
{
InitializeComponent();
}
public MyHostDialog(MyDialog myDialog) : this()
{
this.ElementHost.Child = new MyHostDialogView(myDialog);
if (this.Borderless)
{
this.ElementHost.Child.MouseDown += Child_MouseDown;
this.ElementHost.Child.MouseUp += Child_MouseUp;
this.ElementHost.Child.MouseMove += Child_MouseMove;
}
}
// BELOW CODE DOES NOT WORK, IT WOULD WORK IF Input.MouseButtonEventArgs and Input.MouseEventArgs WERE
// System.Windows.FORMS.MouseEventArgs INSTEAD.
private bool dragging = false;
private System.Drawing.Point startPoint = new System.Drawing.Point(0,0);
private void Child_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
dragging = true;
startPoint = new System.Drawing.Point(e.X, e.Y);
}
private void Child_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
dragging = false;
}
private void Child_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (dragging)
{
System.Drawing.Point p= PointToScreen(e.Location);
Location = new System.Drawing.Point(p.X - this.startPoint.X, p.Y - this.startPoint.Y);
}
}
}
Above code would work if instead of using Input.MouseButtonEventArgs and Input.MouseEventArgs, they were System.Windows.FORMS.MouseEventArgs. So, how to convert that code to work with MouseButtonEventArgs?

c# change panel color from another form

I'm stuck with the following thing.
I want to change the panel color from another Form(ColorForm).
Is it possible?
Code From the MainForm:
public void upperpanel_Paint(object sender, PaintEventArgs e)
{
}
I don't know how to access that upperpanel_Paint in my ColorForm.
I'm opening ColorForm From SettingsForm
Mainform > SettingsForm > ColorForm
public partial class SettingsForm : Form
{
public static event ColourSettingChangedDelegate ColourSettingsChangedEvent;
public delegate void ColourSettingChangedDelegate(Color color);
List<string> adreses;
List<string> bookmarki;
void SelectColour()
{
using (ColorForm colourForm = new ColorForm())
{
if (colourForm.ShowDialog() == DialogResult.OK)
{
//Update colour setting and fire event
OnColourSettingsChanged(colourForm.SelectedColor);
}
}
}
public SettingsForm(List<string> adr, List<string> s)
{
InitializeComponent();
adreses = adr;
bookmarki = s;
}
private void Historyb_Click(object sender, EventArgs e)
{
foreach (Form form in Application.OpenForms)
{
if (form.GetType() == typeof(HistoryForm))
{
form.Activate();
return;
}
}
HistoryForm hf1 = new HistoryForm(adreses);
hf1.Show();
}
private void Bookmarksb_Click(object sender, EventArgs e)
{
BookmarksForm booklist = new BookmarksForm();
booklist.SetAllBookmarks(bookmarki);
booklist.ShowDialog();
}
private void Colorb_Click(object sender, EventArgs e)
{
SelectColour();
}
private void OnColourSettingsChanged(Color color)
{
if (ColourSettingsChangedEvent != null)
ColourSettingsChangedEvent(color);
}
}
Code from ColorForm:
public partial class ColorForm : Form
{
public ColorForm()
{
InitializeComponent();
}
private void Panelcolor_Click(object sender, EventArgs e)
{
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.AnyColor = true;
if (colorDlg.ShowDialog() == DialogResult.OK)
{
upperpanel.BackColor = colorDlg.Color;
}
}
}
Thank you!
Perhaps it would be better to fire a global event when the settings change, or the particular form colour setting changes, and listen for that event on the form where you need to take action.
for example see this pseudo code:
ColourForm:
Form used just to pick a colour, and store the result in a property.
class ColourForm
{
public Color SelectedColor {get;set;}
private void Panelcolor_Click(object sender, EventArgs e)
{
ColorDialog colorDlg = new ColorDialog();
colorDlg.AllowFullOpen = true;
colorDlg.AnyColor = true;
if (colorDlg.ShowDialog() == DialogResult.OK)
{
this.SelectedColor = colorDlg.Color;
}
}
void Cancel()
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
void Save()
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
SettingsForm:
The main form for updating settings, this creates a colour picker form and saved the settings and fires an event if the dialog result of the colour form is an 'ok' result.
class SettingsForm
{
public static event ColourSettingChangedDelegate ColourSettingsChangedEvent;
public delegate void ColourSettingChangedDelegate(Color color);
void SelectColour()
{
using (ColourForm colourForm = new ColourForm())
{
if (colourForm.ShowDialog() == DialogResult.OK)
{
//Update colour setting and fire event
OnColourSettingsChanged(colourForm.SelectedColour);
}
}
}
private void OnColourSettingsChanged(Color color)
{
if (ColourSettingsChangedEvent!=null)
ColourSettingsChangedEvent(color);
}
}
On you Main Form:
The Main form listens for a settings / colour changed event and changes the panel colour to the colour specified in the event when it fires.
class MainForm()
{
//Constructor
MainForm()
{
SettingsForm.ColourSettingsChangedEvent += ColourSettingsChanged;
}
void ColourSettingsChanged(Color color)
{
upperpanel.BackColor = color;
}
}
it would be better to have some kind of settings manager class than have the event on the settings form itself but you should get the idea

PropertyGrid does not update selected object

I want to implement a simple feature where user's can customize the Font of labels.
So I have FontEditor form with the following code:
public partial class FontEditor : Form
{
public Font myFont;
public FontEditor(Font myFont)
{
InitializeComponent();
this.myFont = myFont;
propertyGrid1.SelectedObject = this.myFont;
}
private void FontEditor_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult = DialogResult.OK;
}
}
I use it on a chart control like this:
using (FontEditor fe = new FontEditor(chart1.Titles[0].Font))
{
if (DialogResult.OK == fe.ShowDialog())
{
chart1.Titles[0].Font = fe.myFont;
}
}
When the font editor loads, i can see the following:
If I changed the Size from 18 to 10 and close the window, the SelectedObject (which is my font object from chart title) does not appear to be changing/updating:
Doesn't editing the property grid values should update the SelectedObject?
Okay, I realise the silly mistake. The edits you do on PropertyGrid are actually in propertyGrid1.SelectedObject.
This is how I fixed it:
FontEditor.cs
public partial class FontEditor : Form
{
public FontEditor(Font myFont)
{
InitializeComponent();
propertyGrid1.SelectedObject = myFont;
}
private void FontEditor_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult = DialogResult.OK;
}
public Font UpdatedFont
{
get { return propertyGrid1.SelectedObject as Font; }
}
}
Usage
using (FontEditor fe = new FontEditor(chart1.Titles[0].Font))
{
if (DialogResult.OK == fe.ShowDialog())
{
chart1.Titles[0].Font = fe.UpdatedFont;
}
}
This now works.

Raising an event from child control to parent control

I have a class (which extends Framework Element) which contains within it a number of other Elements.
// Click event coverage area
private Rectangle connectorRectangle;
These shapes all have their event handlers, and when the user clicks on them its working well. Now what I want is to be able to 'handle' a right-click on my class from outside the scope of the class.
So I figured the best way to do it is to handle the event internally, and somehow bubble it to the top
private void connectorRectangle_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
MouseButtonEventArgs args = new MouseButtonEventArgs();
//???
e.Handled = true;
}
The problem is that I have no idea how to raise the event. this.OnMouseRightButtonUp doesn't exist, and all the tutorials I'm finding are for raising custom events.
I'm pretty new to silverlight, so bear with me if I missed something obvious.
Try it :
public Rectangle
{
this.Click += new System.EventHandler(Function);
}
private void Function(object sender, System.EventArgs e)
{
if (((MouseEventArgs)e).Button == MouseButtons.Right)
{
//Your code
}
}
Your "exteded Framework Element class" shouldn't handel the mouse event (or if they handel them, set e.Handled to false). Then the event should bubble up automatically (without reraise the event).
EDIT
public class ExtendedFrameworkElement : Grid
{
public ExtendedFrameworkElement()
{
Border b1 = new Border();
b1.Padding = new Thickness(20);
b1.Background = Brushes.Red;
b1.MouseRightButtonUp += b1_MouseRightButtonUp;
Border b2 = new Border();
b2.Padding = new Thickness(20);
b2.Background = Brushes.Green;
b2.MouseRightButtonUp += b2_MouseRightButtonUp;
b1.Child = b2;
this.Children.Add(b1);
}
private void b1_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//DoSomeThing
e.Handled = false;
}
private void b2_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//DoSomeThing
e.Handled = false;
}
}
Xaml:
<Window x:Class="WpfApplicationTest.MainWindow">
<wpfApplicationTest:ExtendedFrameworkElement MouseRightButtonUp="UIElement_OnMouseRightButtonUp"/>
</Window>
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void UIElement_OnMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
//DoSomeThing
}
}

How to use a personalized property grid with a Chart class?

I am working on a graphing program and I want the user to customize their graph quickly and effectively. I have created a property grid which allows them to do that. I've populated it with the properties of a chart but removes certain elements I don't want the user to have access to. For instance I don't want the user to be able to have access to the accessibility options. So far what I have is
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
magRadioBox.Checked = true;
PropertyGrid propertyGrid1 = new PropertyGrid();
propertyGrid1.CommandsVisibleIfAvailable = true;
propertyGrid1.Text = "Graph and Plotting Options";
propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
this.Controls.Add(propertyGrid1);
}
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "MY Plot Program";
propertyGrid1.SelectedObject = chart1;
}
private void button1_Click(object sender, EventArgs e)
{//some code that is populating my chart(chart1) with data
.... //chart1 being filled with data
}
private void propertyGrid1_PropertyValueChanged(object s , PropertyValueChangedEventArgs e)
{
//Calling the method that will refresh my chart1
myChart.Invalidate();
}
The above code is for my Form. The my "MyChart" class code below sets up my property grid. I automatically get all of the properties of a chart and then can "cherry pick" the ones I don't want the user to have by setting it to [Browsable(false)]
namespace FFT_Plotter
{
[DefaultPropertyAttribute("Text")]
public class MyChart : Chart
{
public event EventHandler PropertyChanged;
private void OnPropertyChanged(object sender, EventArgs e)
{
EventHandler eh = propertyChanged;
if(eh !=null)
{
eh(sender, e);
}
[BrowsableAttribute(false)]
public new System.Drawing.Color BackColor
{
get { return BackColor; }//Here back color is just an example of a property, not necessarily one that I would make non-Browsable
set {
base.BackColor = value;
OnPropertyChanged(this,EventArgs.Empty);
}
}
}
}
The class above gets me so far as having a property grid that has all the properties of a chart and allows me to hide those properties as I see fit. However now I am stuck in understanding how to connect my chart1 to my property grid. An example would be I've removed the text property from the grid. It's no longer visible to the user. Now I want to be able to say change BackColor in the grid which means my chart1 back color changes.
Ok, I took your code and did the following and now changing the Background Color in the property grid changes the chart's background color:
Form1 -
public partial class Form1 : Form
{
private PropertyGrid propertyGrid1;
public Form1()
{
InitializeComponent();
//propertyGrid1 = new PropertyGrid();
propertyGrid1.CommandsVisibleIfAvailable = true;
propertyGrid1.Text = "Graph and Plotting Options";
propertyGrid1.PropertyValueChanged += propertyGrid1_PropertyValueChanged;
this.Controls.Add(propertyGrid1);
}
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "MY Plot Program";
propertyGrid1.SelectedObject = chart1;
}
private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
//Calling the method that will refresh my chart1
chart1.Invalidate();
}
}
[DefaultPropertyAttribute("Text")]
public class MyChart : Chart
{
public event EventHandler PropertyChanged;
private void OnPropertyChanged(object sender, EventArgs e)
{
if(PropertyChanged !=null)
{
PropertyChanged(sender, e);
}
}
[BrowsableAttribute(false)]
public new string Text { get; set; }
[BrowsableAttribute(true)]
public new System.Drawing.Color BackColor
{
get { return base.BackColor; }//Here back color is just an example of a property, not necessarily one that I would make non-Browsable
set
{
base.BackColor = value;
OnPropertyChanged(this,EventArgs.Empty);
}
}
}
Also, in your Form1.Designer.cs file, you have chart1 defined as `System.Windows.Forms.DataVisualization.Charting.Chart you need to change that to be MyChart in the section where it is new'd (need to search for Charting.Chart)

Categories

Resources