Display specific properties in the Property grid - c#

When we press the btnSettings, all the user controls properties will be displayed in Property grid. I want display specific properties (only TemperatureValue and TemperatureUnit), is possible? User control code as follows:
using System;
using System.Windows.Forms;
namespace Temperature
{
public partial class temperatureUc : UserControl
{
public enum temperatureUnit
{
Celsius, // default
Delisle, // °De = (100 − °C) * 3⁄2
Fahrenheit, // °F = °C * 9⁄5 + 32
Kelvin, // °K = °C + 273.15
Newton, // °N = °C * 33⁄100
Rankine, // °R = (°C + 273.15) * 9⁄5
Réaumur, // °Ré = °C * 4⁄5
Rømer // °Rø = °C * 21⁄40 + 7.5
}
public temperatureUc()
{
InitializeComponent();
this.cboTemperatureUnit.DataSource = Enum.GetValues(typeof(temperatureUnit));
}
#region "Event"
public delegate void SettingsStateEventHandler(object sender, EventArgs e);
public event SettingsStateEventHandler settingsStateChanged;
private void OnSettingsChanged(object sender, EventArgs e)
{
if (this.settingsStateChanged != null)
this.settingsStateChanged(sender, e);
}
#endregion
#region "Properties"
private Single _TemperatureValue;
public Single TemperatureValue
{
get
{
return this._TemperatureValue;
}
set
{
if (value.GetType() == typeof(Single))
{
_TemperatureValue = value;
this.txtTemperatureValue.Text = _TemperatureValue.ToString();
}
}
}
private temperatureUnit _TemperatureUnit;
public temperatureUnit TemperatureUnit
{
get
{
return this._TemperatureUnit;
}
set
{
if (value.GetType() == typeof(temperatureUnit))
{
_TemperatureUnit = value;
this.cboTemperatureUnit.Text = _TemperatureUnit.ToString();
}
}
}
#endregion
private void btnSettings_Click(object sender, EventArgs e)
{
this.OnSettingsChanged(sender, e);
}
}
}
User control above code will be called from code bellow:
using System;
using System.Windows.Forms;
using Temperature;
using System.Diagnostics;
using System.Drawing;
namespace TemperatureImplements
{
public partial class Form1 : Form
{
private PropertyGrid pGrid = new PropertyGrid();
public Form1()
{
InitializeComponent();
this.temperatureUc1.settingsStateChanged += new temperatureUc.SettingsStateEventHandler(temperatureUc1_settingsStateChanged);
}
void temperatureUc1_settingsStateChanged(object sender, EventArgs e)
{
pGrid.Size = new Size(300, 500);
pGrid.Location = new Point(300,10);
pGrid.SelectedObject = temperatureUc1;
this.Controls.Add(pGrid);
}
}
}
Picture as follows:

There is a way. This article has a section called "Customizing the PropertyGrid Control" that explains how to do it http://msdn.microsoft.com/en-us/library/aa302326.aspx#usingpropgrid_topic5
Basically you just want to define the AppSettings class to only include TemperatureUnit andTemeratureValue`.
AppSettings appset = new AppSettings();
MyPropertyGrid.SelectedObject = appset;
Define AppSettings as follows;
[DefaultPropertyAttribute("SaveOnClose")]
public class AppSettings{
private bool saveOnClose = true;
private string tempUnit;
private int tempValue;
[CategoryAttribute("Global Settings"),
ReadOnlyAttribute(false),
DefaultValueAttribute("Celsius")]
public string TemperatureUnit
{
get { return tempUnit; }
set { tempUnit = value; }
}
[CategoryAttribute("Global Settings"),
ReadOnlyAttribute(false),
DefaultValueAttribute(0)]
public string TemperatureValue
{
get { return tempValue; }
set { tempValue = value; }
}
}
By the way, I'm changing the category from Misc to Global Settings, don't know if that's what you want but it makes sense when they're the only options. You may have to explicitly declare the other attributes this BrowsableAttribute(false) so they're not displayed but I don't think it's necessary.

There might be a way to hide those properties but I think that's the wrong way to go about it.
Instead of passing the user control itself you should create a model with TemperatureUnit and TemperatureValue. Move your defined events to this model.
Then you need to extend a user control which you pass the model to and listens for these events.
Finally set pGrid.SelectedObject to your model and you'll be good to go.

Related

Trouble passing new object back to main form - C# .NET

I am new to C# and the .NET framework. I am trying to create an array of chocolate orders that shows up as a list on the main screen(MainNavigation). I have a chocolate class and a form(form1) where the user can select which type of chocolate and a new chocolate object is created. I am stuck on trying to pass the new object back to the main form and then showing it in a list on the main form.
MainNavigation form.... I would like value to be the orders that the user creates in form1.
using System;
using System.Windows.Forms;
namespace GatesCandyStore
{
public partial class MainNavigation : Form
{
public MainNavigation()
{
InitializeComponent();
Chocolate[] chocolates = new Chocolate[100];
for (int runs = 0; runs < 100; runs++)
{
chocolates[runs] = value;
}
}
private void btnProcessCandySelection_Click(object sender, EventArgs e)
{
string candy = comboBoxCandySelection.SelectedItem.ToString();
Form1 aForm1 = new Form1(textBoxName.Text, candy);
aForm1.ShowDialog();
}
}
}
Form1 where the user creates a new chocolate order.... Close(newChocolate); does not work.
using System;
using System.Windows.Forms;
namespace GatesCandyStore {
public partial class Form1 : Form
{
Chocolate newChocolate = new Chocolate();
public Form1(string name, string candy)
{
InitializeComponent();
string str = name + " selected : ";
label1.Text = str;
Console.WriteLine(name + " selected : " + candy);
}
private void Form1_Load(object sender, EventArgs e)
{
newChocolate.Flavor = comboBoxChocolateSelection.SelectedItem.ToString();
newChocolate.Cost = 12.5;
newChocolate.GiftWrap = true;
newChocolate.Quantity = 2;
}
private void button1_Click(object sender, EventArgs e)
{
Close(newChocolate);
}
} }
Chocolate Class
namespace GatesCandyStore
{
public class Chocolate
{
#region Fields
public string flavor;
public double cost;
public bool giftWrap;
public int quantity;
#endregion End of Fields
#region Constructors
public Chocolate(string flavor, double cost, bool giftWrap, int quantity)
{
Flavor = flavor;
Cost = cost;
GiftWrap = giftWrap;
Quantity = quantity;
}
#endregion End of Constructors
#region Properties
public string Flavor { get; set; }
public double Cost { get; set; }
public bool GiftWrap { get; set; }
public int Quantity { get; set; }
#endregion End Properties
}
}
here In your question, I'm still not clear what you are doing candy and name in your Form1's constructor.
Assuming you know what you are doing with them and taking your main concern "How to pass newly created object back to main form", I'm suggesting you some correction.
Create A Model class
public delegate void ChocolateAddedEventHander(Chocolate newChocolate);
public class Model
{
//An Event which will be raised when you add new chocolate
public event ChocolateAddedEventHander ChocolateAdded;
//If at any point of program you need whole list of added chocolates
public List<Chocolate> ChocolateList = new List<Chocolate>();
public void AddChocolateInList (Chocolate chocolate)
{
ChocolateList.Add(chocolate);
if (ChocolateAdded != null)
ChocolateAdded(chocolate);
}
}
Your Chocolate class will same as you have shown here.
Make following changes in Program.cs
static void Main()
{
Model modelObj = new Model();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainNavigation(modelObj));
}
As you can see in above code, MainNavigation is accecpting an object of Model class now.
MainNavigation form.
In code you shown in question, you seem to be doing something in constructor of MainNavigation , if array of Chocolate is containing all added chocolates you can use m_modelObj.ChocolateList there. But as I'm not clear what is value there. I'm not adding that part in my answer.
public partial class MainNavigation : Form
{
private Model m_modelObj;
public MainNavigation(Model modelObj)
{
InitializeComponent();
m_modelObj = modelObj;
//subscribing an even of Model class,
//this will handle your logic what you want to perform on adding new Chocolate
m_modelObj.ChocolateAdded += m_modelObj_ChocolateAdded;
}
void m_modelObj_ChocolateAdded(Chocolate newChocolate)
{
//perform your task what you want to do with newly added chocolate
//if you want whole list of chocolates
List<Chocolate> chocolateList = m_modelObj.ChocolateList;
}
private void btnProcessCandySelection_Click(object sender, EventArgs e)
{
string candy = comboBoxCandySelection.SelectedItem.ToString();
Form1 aForm1 = new Form1(textBoxName.Text, candy, m_modelObj);
aForm1.ShowDialog();
}
}
Note that, now Form1 will accept three parameters, third as in object of Model class
Form1 where you are adding chocolate.
public partial class Form1 : Form
{
Model m_model;
public Form1(string name, string candy, Model modelObj)
{
InitializeComponent();
m_model = modelObj;
//Not sure what you are doing here, but it will work
string str = name + " selected : ";
label1.Text = str;
Console.WriteLine(name + " selected : " + candy);
}
private void button1_Click(object sender, EventArgs e)
{
//adding new chocolate to list;
Chocolate newChocolate = new Chocolate(comboBoxChocolateSelection.SelectedItem.ToString(), 12.5, true, 2);
m_model.AddChocolateInList(newChocolate);
this.Close();
}
}
One more thing I will suggest, naming of class and member should be proper, It will help a lot while debugging and code reviewing.

variable and textbox mapping in c# without using textbox changed event

I'm trying a code which changes the TextBox values when variable mapped with it changes accordingly without using TextBox changed event. I am not finding any clue to where to start please help me.
Here is the code:
public void varChange(TextBox text)
{
String name;
name="sachin";
text.Text = name;
MessageBox.Show("" + text.Text);
}
You can "extend" TextBox :
public class MeTextBox : TextBox
{
public override string Text
{
get
{
return base.Text;
}
set
{
//base.Text = value; // use it or not .. whatever
MyTextWasChanged();
}
}
void MyTextWasChanged()
{
String name;
name="sachin";
//text.Text = name;
base.Text = name;
MessageBox.Show("" + text.Text);
}
}
If that's not what you're looking for then give some more details and I'll update this answer.
You can use a BindingSource
public partial class Form1 : Form
{
private System.Windows.Forms.BindingSource form1BindingSource;
public string BindedProp { get; set; } //Variable or property binded with TextBox
public Form1()
{
InitializeComponent();
this.form1BindingSource = new System.Windows.Forms.BindingSource(new System.ComponentModel.Container());
this.form1BindingSource.DataSource = typeof(binding.Form1);
this.textBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.form1BindingSource, "BindedProp", true));
this.form1BindingSource.DataSource = this;
}
//add a button control to assing value code event click
private void btAssingValueProperty_Click(object sender, EventArgs e)
{
BindedProp = "Value assigned";
form1BindingSource.ResetBindings(false);
}
//add a other button control to show value code event click
private void btShowValueProperty_Click(object sender, EventArgs e)
{
MessageBox.Show(BindedProp);
}
}

Unable to register click event from composite control to parent form

What I am attempting to do is create a complex control that has a picture box, track slider and numeric up down controls. In the parent form, when the user clicks on an image, then this composite control appears and the background color is then sent to it and the image in the control is then set with that background color. Then if the user clicks on the image on the composite control, the parent form is then notified of the click event and then subsequently removes that specific composite control from the parent form.
Composite Control code
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace ctlClusterControlLib
{
public partial class UserControl1 : UserControl
{
private Color colImageBackground;
private int intThreadCount;
private PictureBox pictureBoxControl; // Compiler informs me that this is never assigned to and will always have its default value null.
private TrackBar trackBar; // Compiler informs me that this is never assigned to and will always have its default value null.
private NumericUpDown numericUpDown; // Compiler informs me that this is never assigned to and will always have its default value null.
private string strImageToolTip1;
private string strImageToolTip2;
private static object EventSubmitKey = new object();
public UserControl1()
{
InitializeComponent();
}
public Color ImageBackground
{
get { return colImageBackground; }
set { colImageBackground = value; Invalidate(); }
}
public int ThreadCount
{
get { return intThreadCount; }
set { intThreadCount = value; }
}
[
Category("Action"),
Description("Raised when the user clicks on the image.")
]
public event EventHandler PictureClick
{
add { Events.AddHandler(EventSubmitKey, value); }
remove { Events.RemoveHandler(EventSubmitKey, value); }
}
public event EventHandler TrackBarScroll
{
add { trackBar.Scroll += value; }
remove { trackBar.Scroll -= value; }
}
public event EventHandler numericUpDownChange
{
add { numericUpDown.ValueChanged += value; }
remove { numericUpDown.ValueChanged -= value; }
}
public string ImageToolTip1
{
get { return strImageToolTip1; }
set { strImageToolTip1 = value; }
}
public string ImageToolTip2
{
get { return strImageToolTip2; }
set { strImageToolTip2 = value; }
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
numericUpDown1.Value = trackBar1.Value;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
trackBar1.Value = Convert.ToInt32(numericUpDown1.Value);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Color c = Color.FromArgb(0xFF, colImageBackground);
pictureBox1.BackColor = c;
}
}
}
Parent Form CS relevant section:
private void newPictureBox_Click(object sender, EventArgs e)
{
UserControl1 _UserControl = new UserControl1();
PictureBox _PictureBox = (PictureBox)sender;
string _NewControlClusterName = "_New" + _PictureBox.Name;
_UserControl.Name = _NewControlClusterName;
_UserControl.ThreadCount = 16;
_UserControl.ImageBackground = _PictureBox.BackColor;
_UserControl.Dock = DockStyle.Top;
_UserControl.PictureClick += new EventHandler(ClusterControl_Click);
//_UserControl.TrackBarScroll += new EventHandler(GetTartanCode);
panel3.Controls.Add(_UserControl);
panel3.Controls.SetChildIndex(_UserControl, 0);
}
And I am having intermittent issues with raising the click event to the parent form using this control.
I have tried everything I can find in Google and Stack Overflow with no joy. My questions are this:
Am I even in the right ballpark?
Is this something that needs to be coded in the parent form cs file?
Is this something that needs to be reconfigured in the composite control cs file?
Is this something that needs to be configured in both files?
I believe I have a solution.
What I was not doing was directly assigning the request to the control I wanted to register the event for. Instead I was assigning it to a new control and therefore nothing would happen.
public event EventHandler PictureClick
{
add { pictureBox1.Click += value; }
remove { pictureBox1.Click -= value; }
}
And so far, It works every time.

Panel does not contain a constructor that takes 0 arguments

I need to load a User Control in my panel1 inside Form1.cs, the problem is that the UserControl (AudioPlaybackPanel) contains an ImportingConstructor ([ImportMany]IEnumerable<>) and I can't figure out what two arguments I should have in the Form1 AudioPlaybackPanel(????).
The error I get is: 'NAudio.App.AudioPlaybackPanel' does not contain a constructor that takes 0 arguments
Here is the Form1.cs
namespace NAudio.App
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
AudioPlaybackPanel myPanel = new AudioPlaybackPanel(????);
panel1.Controls.Add(myPanel);
}
}
}
And this is my User Control Panel (AudioPlaybackPanel.cs):
namespace NAudio.App
{
[Export]
public partial class AudioPlaybackPanel : UserControl
{
private IWavePlayer waveOut;
private string fileName = null;
private WaveStream fileWaveStream;
private Action<float> setVolumeDelegate;
[ImportingConstructor]
public AudioPlaybackPanel([ImportMany]IEnumerable<IOutputDevicePlugin> outputDevicePlugins)
{
InitializeComponent();
LoadOutputDevicePlugins(outputDevicePlugins);
}
[ImportMany(typeof(IInputFileFormatPlugin))]
public IEnumerable<IInputFileFormatPlugin> InputFileFormats { get; set; }
private void LoadOutputDevicePlugins(IEnumerable<IOutputDevicePlugin> outputDevicePlugins)
{
comboBoxOutputDevice.DisplayMember = "Name";
comboBoxOutputDevice.SelectedIndexChanged += new EventHandler(comboBoxOutputDevice_SelectedIndexChanged);
foreach (var outputDevicePlugin in outputDevicePlugins.OrderBy(p => p.Priority))
{
comboBoxOutputDevice.Items.Add(outputDevicePlugin);
}
comboBoxOutputDevice.SelectedIndex = 0;
}
void comboBoxOutputDevice_SelectedIndexChanged(object sender, EventArgs e)
{
panelOutputDeviceSettings.Controls.Clear();
Control settingsPanel;
if (SelectedOutputDevicePlugin.IsAvailable)
{
settingsPanel = SelectedOutputDevicePlugin.CreateSettingsPanel();
}
else
{
settingsPanel = new Label() { Text = "This output device is unavailable on your system", Dock=DockStyle.Fill };
}
panelOutputDeviceSettings.Controls.Add(settingsPanel);
}
private IOutputDevicePlugin SelectedOutputDevicePlugin
{
get { return (IOutputDevicePlugin)comboBoxOutputDevice.SelectedItem; }
}
// The rest of the code continues from here on...
}
}
Here is the Interface:
namespace NAudio.App
{
public interface IOutputDevicePlugin
{
IWavePlayer CreateDevice(int latency);
UserControl CreateSettingsPanel();
string Name { get; }
bool IsAvailable { get; }
int Priority { get; }
}
}
And just in case, here is one of the plugins:
DirectSoundOutPlugin.cs
namespace NAudio.App
{
[Export(typeof(IOutputDevicePlugin))]
class DirectSoundOutPlugin : IOutputDevicePlugin
{
private DirectSoundOutSettingsPanel settingsPanel;
private bool isAvailable;
public DirectSoundOutPlugin()
{
this.isAvailable = DirectSoundOut.Devices.Count() > 0;
}
public IWavePlayer CreateDevice(int latency)
{
return new DirectSoundOut(settingsPanel.SelectedDevice, latency);
}
public UserControl CreateSettingsPanel()
{
this.settingsPanel = new DirectSoundOutSettingsPanel();
return this.settingsPanel;
}
public string Name
{
get { return "DirectSound"; }
}
public bool IsAvailable
{
get { return isAvailable; }
}
public int Priority
{
get { return 3; }
}
}
}
Please help!
The error doesn't say it expects two arguments... it just says it doesn't take 0.
The constructor expects a single parameter - an IEnumerable<IOutputDevicePlugin>:
public AudioPlaybackPanel([ImportMany]IEnumerable<IOutputDevicePlugin> outputDevicePlugins)
{
...
}
You need to find something that implements the IOutputDevicePlugin interface and pass a collection of it, even if it's just an empty collection. (Passing null to the constructor will allow it to compile but will throw a runtime exception when you hit the loop in LoadOutputDevicePlugins.)
Considering the update to your question, something like this will get you up and running (although I doubt it means very much to pass an empty list):
var myPanel = new AudioPlaybackPanel(new List<DirectSoundOutPlugin>());
panel1.Controls.Add(myPanel);
It's worth asking whether you actually need to copy AudioPlaybackPanel.cs from the NAudio demo in its entirety. The reason it has this constructor is that it tries to demonstrate how you can use each and every one of NAudio's IWavePlayer implementations. But in a normal real-world application you would just select the one that was most appropriate for your use. e.g.
this.waveOut = new WaveOut();
waveOut.Init(new AudioFileReader("my file.mp3");
waveOut.Play();
So there's no need to incorporate the plug-in architecture from that particular demo, if all you want is just to play audio files.

GridView FocusedRowChanged - Child Class object

I need some help here.
I've created a child class called MyEditorRow from DevExpress EditorRow, and added 3 properties
public class myEditorRow : EditorRow
{
public myEditorRow()
{
}
private string inRowDescription = null;
public string RowDescription
{
get { return inRowDescription; }
set { inRowDescription = value; }
}
private bool inRequired = false;
public bool Required
{
get { return inRequired; }
set { inRequired = value; }
}
private bool inInherits = false;
public bool Inherits
{
get { return inInherits; }
set { inInherits = value; }
}
Second part of the code somewhere in the program adds instance of MyEditorRow to DevExpress VGrid Control.
vgcGrid.Rows.Add(Row);
My question is this: How can I link MyEditorRow class with DevExpress VGrid Control FocusedRowChanged event, so I can get my custom properties when row focus changes.
Thanks
The e.Row parameter is of the BaseRow type. So, to obtain an instance of the MyEditorRow object in the FocusnedRowChanged event handler, use the following code:
private void vGridControl1_FocusedRowChanged(object sender, DevExpress.XtraVerticalGrid.Events.FocusedRowChangedEventArgs e) {
if(e.Row is myEditorRow) {
myEditorRow row = ((myEditorRow)e.Row);
// your code here
}
}

Categories