Single-Variable Binding in Win Forms: What am I doing wrong? - c#

I've been trying to make binding work for two labels in a WinForm, but I can't seem to figure out what I'm doing wrong. Currently, I'm implementing the INotifyPropertyChanged interface, and rigged it to a couple of properties within a Form. The current classes this affects are SessionForm.cs, the actual form, and Session.cs, the place where I keep all the information of the program. The labels in question, which are not mentioned in either class, are L_No, which holds the numerical reference of the Note in the musical Scale, and L_Note, which holds the visceral Note value (e.g. C, C#, etc.).
Allow me to explain what everything does within the classes. The program is designed to test your scale knowledge by asking you, based on the your chosen scale, what nth note of the scale is. You use the buttons on the form to make your choice.
These choices are recorded within the Session class, which has been edited to make this more succinct. The array of integers holds the indices of the notes in relation to the scale array, which is in the Scale object. For example, a typical Note array may hold these values: {1,3,0,2,6,1,3,...}. By using the array in the Scale object as a reference, these would translate into musical notes (e.g. D, F, C, E, B, D, F,...). The player's choices are stored within an array of NoteData objects.
In SessionForm.cs I'm manipulating that information over time. Each time a choice is or isn't made (depending on whether or not they attempted to guess in time), the value of the two Labels are changed: L_No, and L_Note. These two Labels are manipulated by the variables NoteIndex and LastNote, respectively. When these change in value, NotifyPropertyChanged occurs, and then the Labels should be updated...but they're not doing so.
Now, in the design section of the form, in the Properties window, I set up the Text property of each Label to be bound to their respective variables within the form, and set to update upon Property Change, but nothing seems to be working.
So what am I doing wrong?
Session.cs:
public class Session
{
public struct NoteData
{
public int Note;
public bool Correct;
public int GuessTime;
}
public Scale Scale;
/// <summary>
/// Holds the notes for one game
/// </summary>
public int[] Notes { get; private set; }
public NoteData[] Data { get; private set; }
/// <summary>
/// Creates a Session
/// </summary>
/// <param name="difficulty">The difficult of the session, refer to the Resources Class for determination.</param>
/// <param name="scale_used">The scale to be used. Refer to the Resources Class for determination.</param>
/// <param name="notes">The notes being used within this Session</param>
public Session(Resources.Difficulties difficulty, Scale scale_used, int[] notes)
{
ID = DateTime.Now;
Diff = difficulty;
Scale = scale_used;
Notes = notes;
Data = new NoteData[notes.Length];
internalIndex = 0;
}
/// <summary>
/// Stores Note input for each guessed
/// </summary>
/// <param name="index">The index of the note the player is currently on</param>
/// <param name="correct">Was the guess correct?</param>
/// <param name="remaining_time">How long did it take for them to guess?</param>
public void StoreNoteInput(int index, bool correct, int remaining_time)
{
if (internalIndex < Data.Length)
Data[internalIndex++] = new NoteData(index, remaining_time, correct);
}
}
SessionForm.cs:
public partial class SessionForm : Form, INotifyPropertyChanged
{
public Session curSession { get; private set; }
Resources.Notes last_note;
/// <summary>
/// The note index number in relation to the scale
/// </summary>
public int NoteIndex
{
get
{ return note_index; }
private set
{
if (note_index != value)
{
note_index = value;
NotifyPropertyChanged("NoteIndex");
}
}
}
/// <summary>
/// Represents the previous note being tested
/// </summary>
public Resources.Notes LastNote
{
get
{
return last_note;
}
private set
{
if (last_note != value)
{
last_note = value;
NotifyPropertyChanged("LastNote");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void TickDownTimer_Tick(object sender, EventArgs e)
{
remainingTime -= countingDown ? 1000 : 100;
if (remainingTime == 0)
{
if (countingDown)
{
countingDown = false;
TickDownTimer.Interval = 100;
}
if (curIndex > 0)
{
//you ran out of time on the last note
RecordNoteInput(curIndex - 1, false);
}
NextNote();
}
SetTimerText();
}
private void RecordNoteInput(int index, bool correct)
{
curSession.StoreNoteInput(index, correct, remainingTime);
NoteIndex = curSession.Notes[curIndex - 1];
LastNote = curSession.Scale.Notes[NoteIndex];
L_Note.ForeColor = correct ? Color.Green : Color.Red;
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
UPDATE: Here's the binding code that comes from SessionForm.Designer.cs:
this.sessionFormBindingSource1 = new System.Windows.Forms.BindingSource(this.components);
this.sessionFormBindingSource2 = new System.Windows.Forms.BindingSource(this.components);
this.sessionFormBindingSource = new System.Windows.Forms.BindingSource(this.components);
//
// L_Note
//
this.L_Note.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.sessionFormBindingSource1, "LastNote", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged, "C"));
this.L_Note.Text = " ";
//
// L_No
//
this.L_No.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.sessionFormBindingSource2, "NoteIndex", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged, "1", "N0"));
this.L_No.Text = " ";

The problem is the way you call NotifyPropertyChanged:
NotifyPropertyChanged("note_index");
and
NotifyPropertyChanged("last_note");
Just remove the strings from the calls like this
NotifyPropertyChanged();
and everything should be fine.
Edit: If it's not, then your bindings are not initialized correctly. Prove:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
namespace Tests
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}
class TestForm : Form, INotifyPropertyChanged
{
public TestForm()
{
var label = new Label { Parent = this, Left = 16, Top = 16, AutoSize = false, BorderStyle = BorderStyle.FixedSingle };
label.DataBindings.Add("Text", this, "NoteIndex");
var timer = new Timer { Interval = 200, Enabled = true };
timer.Tick += (sender, e) => NoteIndex = (NoteIndex + 1) % 10;
}
int note_index;
public int NoteIndex
{
get { return note_index; }
private set
{
if (note_index != value)
{
note_index = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

Related

Calculate properties using items in List with conditions

I have a list object that has several properties that I want to use for calculations for an model properties.
something like:
List<Cars>
that has properties for Wheels/Windows/HasRoof/FuelType, etc.
I have a model for "Parts" (class example below) that I want to fill but I have a few rules to apply, I'm going to pseudoCode what I think I should do, but I'm not sure if this is the approach for this:
public class Parts
{
public int AmountOfWheels { get; set; }
public int AmountOfWheelsForFuelTypeGas { get; set; }
public AmountOfWindowsForCarsWithRoof Type { get; set; }
}
public Parts Parts { get; set; }
this is what I want to fill:
foreach (var item in Cars)
{
Parts.AmountOfWheels =+ item.Wheels;
Parts.AmountOfWheelsForFuelTypeGas // <-- This is what I don't know
Parts.AmountOfWindowsForCarsWithRoof // <-- This is what I don't know
}
Then later I want to show the user this Parts object in a webApp, but I'm not sure how to populate this object.
The part I'm not sure if it's ok to do the calculations like this or shall I do something in the object model with properties
I think I know what you're getting at, but tell me if I miss the mark!
For most UIs including web apps, the UI box that is displaying something like AmountOfWheels is bound to changes of that property using the INotifyPropertyChanged interface. If your Parts class implements that interface, then when this line in your code executes:
Parts.AmountOfWheels =+ item.Wheels;
that will change the value of AmountOfWheels property and that will fire a property changed event. The calculation in turn will set the other properties (like AmountOfWheelsForFuelTypeGas). That fires its own changed event and the UI just picks up on that property change and shows the value.
// A class that notifies when its properties change
class Part : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// The private 'backing store' of the variable which is a Field
/// </summary>
private int _amountOfWheels = 1;
/// <summary>
/// The public property
/// </summary>
public int AmountOfWheels
{
get => _amountOfWheels;
set
{
if (_amountOfWheels != value)
{
_amountOfWheels = value;
OnPropertyChanged();
}
}
}
int _amountOfWheelsForFuelTypeGas = -1;
public int AmountOfWheelsForFuelTypeGas
{
get => _amountOfWheelsForFuelTypeGas;
set
{
if (_amountOfWheelsForFuelTypeGas != value)
{
_amountOfWheelsForFuelTypeGas = value;
OnPropertyChanged();
}
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
switch (propertyName)
{
case nameof(AmountOfWheels):
onAmountOfWheelsChanged();
break;
}
}
private void onAmountOfWheelsChanged()
{
// Perform some calculation based on AmountOfWheels.
AmountOfWheelsForFuelTypeGas = TestDataGenerator.Next(0,10);
}
private Random TestDataGenerator = new Random();
}
Test driver for it:
class Program
{
static void Main(string[] args)
{
var part = new Part();
part.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case nameof(Part.AmountOfWheelsForFuelTypeGas):
Console.WriteLine($"Amount of Wheels {part.AmountOfWheels} = (Rando test data){part.AmountOfWheelsForFuelTypeGas}");
break;
}
};
for (int i = 0; i < 5; i++)
{
part.AmountOfWheels = i;
}
}
}

object reference is required, also dump object into messagebox tips

i'm getting an error with this code new RoutedEventHandler(Notifications.showNotifications(window)); saying:
An object reference is required for the non-static field, method, or
property 'Notifications.showNotifications(Window)'
Also, can I get an example of how I could dump out each Dictionary object from within my _notifications object in the runtimeObject class? I need to do this when showNotifications is called!
When I say dump out, based on the test notifications which I try to add in the code, I just want to display a MessageBox to show that they are being added, so using the code above the MessageBox would show:
MessageBox
Error Code: 1, Text: Error 1
Error Code: 2, Text: Normal Message
Error Code: 3, Text: Tip
App.xaml.cs
namespace Test_Project
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Startup
Window main = new MainWindow();
main.Show();
//Attach Event Handlers to MainWindow
if (!attachEventHandlers(main))
{
MessageBox.Show("Fatal Error: Unable to attach event handlers, contact administrator!",
"Fatal Error!",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
}
}
public bool attachEventHandlers(Window window)
{
//window.MouseMove += new RoutedEventHandler(Notifications.showNotifications(window));
return true;
}
}
public class Notifications
{
/// <summary>
/// Show the notifications
/// </summary>
/// <param name="window"></param>
public void showNotifications(Window window)
{
// Find the resource, then cast it to a runtimeObject
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
//Create messagebox with all the notifications in to test
}
public bool addNotifications()
{
// Find the resource, then cast it to a runtimeObject
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
//Create Dictionary
Dictionary<int, string> arr = new Dictionary<int, string>();
arr.Add(1, "Error 1");
arr.Add(2, "Normal Message");
arr.Add(3, "Tip");
//Create test notifications
runtime.notifications.Add(arr);
return true;
}
}
/// <summary>
/// Global values for use during application runtime
/// </summary>
public class runtimeObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
//Can the application be closed?
private bool _inProgress = false;
public bool inProgress
{
get { return _inProgress; }
set
{
if (_inProgress != value)
{
_inProgress = value;
OnPropertyChanged("inProgress");
}
}
}
/// <summary>
/// Notifications held
/// Array((int)type,(string)"message")
/// </summary>
private List<Dictionary<int, string>> _notifications;
public List<Dictionary<int, string>> notifications
{
get { return _notifications; }
set
{
if (_notifications != value)
{
_notifications = value;
OnPropertyChanged("notifications");
}
}
}
//Selected folder to search in
private int _uploadProgress = 0;
public int uploadProgress
{
get { return _uploadProgress; }
set
{
if (_uploadProgress != value)
{
//int Angle = (_uploadProgress * 360) / 100;
//Classes.CircularProgress.RenderArc(Angle);
_uploadProgress = value;
OnPropertyChanged("uploadProgress");
}
}
}
}
}

DataContext - ListView - Refresh UI - INotifyPropertyChanged

Working on an windows store app, I try to update/refresh a listView when some data is updated. But despite all samples and documentations I read, it doesn't work...
Here my code behind :
(I do not provide my xaml files, it's just a sample listView).
So the class which implements the INotifyPropertyChanged interface:
public class Download : INotifyPropertyChanged
{
public enum DownloadState
{
Running,
Waiting,
Pausing,
Paused,
Cancelling,
Cancelled
};
private String Uri;
private StorageFile storageFile;
private String tempFileName;
private String fileName;
private String version ;
private long totalSize ;
private long downloadedBytes;
private DownloadState state;
private Protocol protocol;
public Download(String Uri, StorageFile file, String fileName, String version, long totalSize, Protocol protocol)
{
this.Uri = Uri;
this.storageFile = file;
this.tempFileName = "";
this.fileName = fileName;
this.version = version;
this.totalSize = totalSize;
this.downloadedBytes = 0;
this.state = DownloadState.Waiting;
this.protocol = protocol;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
System.Diagnostics.Debug.WriteLine("Update!"); //ok
if (PropertyChanged != null)
{
//PropertyChanged is always null and shouldn't.
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public DownloadState State
{
get{return this.state;}
set {
this.state = value;
NotifyPropertyChanged();
}
}
//+some others methods
}
}
And the main page of the metro app :
// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237
namespace ClientAirNavLight_WS
{
/// <summary>
/// A basic page that provides characteristics common to most applications.
/// </summary>
public sealed partial class MainPage : ClientAirNavLight_WS.Common.LayoutAwarePage
{
/// <summary>
/// Represent a Web Service proxy.
/// </summary>
private AirNavLight_WSClientClient proxyWS;
/// <summary>
/// Initiialize the component of the application's main page.
/// </summary>
public MainPage()
{
this.InitializeComponent();
}
/// <summary>
/// Populates the page with content passed during navigation. Any saved state is also
/// provided when recreating a page from a prior session.
/// </summary>
/// <param name="navigationParameter">The parameter value passed to
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
/// </param>
/// <param name="pageState">A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.</param>
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
}
/// <summary>
/// Preserves state associated with this page in case the application is suspended or the
/// page is discarded from the navigation cache. Values must conform to the serialization
/// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary>
/// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
protected override void SaveState(Dictionary<String, Object> pageState)
{
}
//Simulate data update.
private async void Button_Click(object sender, RoutedEventArgs e)
{
object selected = this.ListResult.SelectedItem;
if (selected != null)
{
//simulate an update in data.
// ListView should be refresh in order to reflect changes made here.
Download dl = (Download)selected;
if (dl.State == Download.DownloadState.Paused)
{
dl.State = Download.DownloadState.Running;
}
else
{
dl.State = Download.DownloadState.Paused;
}
}
else
{
//Just add an item to the list view.
StorageFile file = await this.getStorageFile("test");
Download dl = new Download("192.128.2.14", file, "test", "1.2", 100, Protocol.HTTP);
this.ListResult.Items.Add(dl);
this.ListResult.DataContext = dl;// Does not work.
}
}
private async Task<StorageFile> getStorageFile(String suggestedFileName)
{
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.FileTypeChoices.Add("Application/pdf", new List<string>() { ".pdf" });
savePicker.FileTypeChoices.Add("Archive", new List<string>() { ".zip", ".rar", ".7z" });
savePicker.FileTypeChoices.Add("Plain-text", new List<string>() { ".txt" });
// Default file name if the user does not type one in or select a file to replace
savePicker.SuggestedFileName = suggestedFileName;
return await savePicker.PickSaveFileAsync();
}
}
}
So How am I supposed to use listView.DataContext? Am I misunderstanding how use INotifyPropertyChanged?
EDIT :
How my listView is define :
<ListView x:Name="ListResult" HorizontalAlignment="Left" Height="200" Margin="10,56,0,0" VerticalAlignment="Top" Width="653" SelectionMode="Single"/>
Why are you setting this.ListResult.DataContext = dl? When dealing with ListViews, the ItemsSource is the collection for the all the objects that get iterated, not the DataContext. Furthermore, ItemsSource should be a collection and not one item. So if you're binding to a property, that property should exist as an item's property in the ItemsSource collection.
However, it looks like you don't have a collection so you're adding the dl directly to the ListView with this.ListResult.Items.Add(dl). That approach should work, however take out the this.ListResult.DataContext = dl or set this.ListResult.ItemsSource to a collection and add dl to that collection
I'm not familiar with [CallerMemberName] but if you're having problems with propertyName being null, try the following
public DownloadState State
{
get{return this.state;}
set {
if( this.state != value )
{
this.state = value;
NotifyPropertyChanged("State");
}
}
}
Furthermore, all properties that you want to bind to should be public and call NotifyPropertyChanged, like the following
private long totalSize ;
public long TotalSize
{
get{return this.totalSize;}
set {
if( this.totalSize != value )
{
this.totalSize = value;
NotifyPropertyChanged("TotalSize");
}
}
}
In your Download class, the only Property that will update in the UI is State, since it has a getter and setter.
Without your XAML it's not possible to see what you are trying to display, but normally, you would bind properties of your DataContext object (dl in this case) to different controls in a datatemplate that the listview could then display.
But these properties need to be public and have getters and setters for INotifyPropertyChanged to update the UI that these properties are bound to.
For instance, if you wanted the filename to show up in the ListView, you would need, as a minimum, to declare the filename property like this:
public String fileName {get; set; }
Zangdak -- One way around that problem is each time the items change in your collection just set set the ItemSource of the ListView to null and then set it back to your collection. If you do this the UI will update and you will see your new items added to your collection.
Paige Ake

UltraTree Binding to Business Object Display Text

I'm binding an UltraTree control (version 10.3) to a custom data source, like so:
public void Populate(List<FilterDimension> data)
{
DataBindings.Clear();
DataSource = data;
Nodes[0].DataColumnSetResolved.NodeTextColumn = Nodes[0].DataColumnSetResolved.Columns["DisplayText"];
}
My expectation is that changing the DisplayText property on any of the bound FilterDimension objects will cause the UltraTree node's text to update. In reality, the text in the tree does not update, and the PropertyChanged event remains null indicating that the UltraTree doesn't even listen for this notification. How do I get the UltraTree to listen for property changes in FilterDimension?
Here's the relevant code from FilterDimension:
internal class FilterDimension : INotifyPropertyChanged
{
private string _displayText = null;
private string _name = null;
private BindingList<string> _values = new BindingList<string>();
/// <summary>
/// Gets or sets the display friendly name.
/// </summary>
public string Name
{
get { return _name; }
set
{
_name = value;
FirePropertyChangedNotification("Name");
if (_displayText == null) { FirePropertyChangedNotification("DisplayText"); }
}
}
/// <summary>
/// Gets or sets the display text that is used in TreeView nodes. When null, uses the Name.
/// </summary>
public string DisplayText
{
get { return _displayText ?? Name; }
set { _displayText = value; FirePropertyChangedNotification("DisplayText"); }
}
/// <summary>
/// Gets a read/write list of values. Is never null.
/// </summary>
public BindingList<string> Values
{
get { return _values; }
set { _values = value ?? new BindingList<string>(); }
}
#region Events
public event PropertyChangedEventHandler PropertyChanged;
protected void FirePropertyChangedNotification(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
It turns out that all I needed to do was change to BindingList<FilterDimension> instead of List<FilterDimension... I completely missed that the control expects notifications to bubble up from the list.

can't get value of trackbar on menu strip

I've added a trackbar to menu strip manually because vs 2008 doesn't allow me to do.
However, i can't get the value of trackbar.
Form1.cs:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.MenuStrip |
ToolStripItemDesignerAvailability.ContextMenuStrip)]
public class TrackBarMenuItem : ToolStripControlHost
{
private TrackBar trackBar;
public TrackBarMenuItem()
: base(new TrackBar())
{
this.trackBar = this.Control as TrackBar;
trackBar.TickFrequency = 1;
trackBar.Maximum = 255;
trackBar.LargeChange = 5;
trackBar.SmallChange = 2;
}
}
Form1.Designer.cs:
private TrackBarMenuItem trackBar1;
//
// trackBar1
//
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(104, 25);
and this is how i need to use it:
private void trackBar1_Scroll(object sender, System.EventArgs e)
{
int valueB = trackBar1.Value;
pictureBox2.Image = Deneme(new Bitmap(pictureBox1.Image),valueB);
}
but i get this error:
Error 1 'goruntuIsleme2.Form1.TrackBarMenuItem' does not contain a
definition for 'Value' and no extension method 'Value' accepting a
first argument of type 'goruntuIsleme2.Form1.TrackBarMenuItem' could
be found (are you missing a using directive or an assembly reference?)
any ideas?
Expose the value of the internal Trackbar object as a property on your new TrackBarMenuItem class:
Value { get { return trackBar.Value; } set { trackBar.Value = value; } }
i am adding the solution i found. someone might need it:
[System.ComponentModel.DesignerCategory("code")]
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ContextMenuStrip | ToolStripItemDesignerAvailability.MenuStrip)]
public partial class ToolStripMenuItem : ToolStripControlHost
{
public ToolStripMenuItem()
: base(CreateControlInstance())
{
}
/// <summary>
/// Create a strongly typed property called TrackBar - handy to prevent casting everywhere.
/// </summary>
public TrackBar TrackBar
{
get
{
return Control as TrackBar;
}
}
/// <summary>
/// Create the actual control, note this is static so it can be called from the
/// constructor.
///
/// </summary>
/// <returns></returns>
private static Control CreateControlInstance()
{
TrackBar t = new TrackBar();
t.AutoSize = false;
t.Height = 16;
t.Maximum = 255;
// Add other initialization code here.
return t;
}
[DefaultValue(0)]
public int Value
{
get { return TrackBar.Value; }
set { TrackBar.Value = value; }
}
/// <summary>
/// Attach to events we want to re-wrap
/// </summary>
/// <param name="control"></param>
protected override void OnSubscribeControlEvents(Control control)
{
base.OnSubscribeControlEvents(control);
TrackBar trackBar = control as TrackBar;
trackBar.ValueChanged += new EventHandler(trackBar_ValueChanged);
}
/// <summary>
/// Detach from events.
/// </summary>
/// <param name="control"></param>
protected override void OnUnsubscribeControlEvents(Control control)
{
base.OnUnsubscribeControlEvents(control);
TrackBar trackBar = control as TrackBar;
trackBar.ValueChanged -= new EventHandler(trackBar_ValueChanged);
}
/// <summary>
/// Routing for event
/// TrackBar.ValueChanged -> ToolStripTrackBar.ValueChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void trackBar_ValueChanged(object sender, EventArgs e)
{
// when the trackbar value changes, fire an event.
if (this.ValueChanged != null)
{
ValueChanged(sender, e);
}
}
// add an event that is subscribable from the designer.
public event EventHandler ValueChanged;
// set other defaults that are interesting
protected override Size DefaultSize
{
get
{
return new Size(200, 16);
}
}
}
if you add this to your code, you will be able to add trackbars as ToolStripMenuItem via Designer.
Does your class TrackBarMenuItem has a property called Value? If not, you have to add it.

Categories

Resources