|
Thanks for the reply. I tried to keep it brief the first time
(I've changed the class names to avoid confusion w the word Image)
So my basic class is called Cover (as in album cover). For now, it is just a picturebox with a property that allows me to change the background colour.
I then have the collection Covers :
public class Covers : System.Collections.CollectionBase
{
#region Indexer
public Cover this[int index]
{
get
{
if (index < 0 || index > this.List.Count)throw new ArgumentOutOfRangeException();
return (Cover)this.List[index];
}
}
#endregion
#region Adding methods
public Covers Add(Color _colour)
{
Cover newCover = new Cover();
newCover.BackColor = _colour;
this.List.Add(newCover );
return this;
}
#endregion
}
And then finally there is the CoverView, which I would like to display the collection of Covers and eventually scroll through them. Originally I was trying this with a panel that I will move manually, but I just discovered the FlowObjectPanel so I am trying that:
public partial class CoverView : UserControl
{
#region Members & Constructor
private Covers vCovers;
public CoverView()
{
InitializeComponent();
SetStyle(ControlStyles.DoubleBuffer, true);
this.vCovers = new Covers();
}
#endregion
#region Properties
[System.ComponentModel.Browsable(false)]
public Covers Covers
{
get
{
return this.vCovers ;
}
}
#endregion;
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
vCovers[0].Visible = true;
vCovers[0].Parent = this;
vCovers[0].Location = new Point(0, 0);
}
}
I could do a direct paint, but I do want the Cover objects to be selectable so I may have to stick with this path for the moment. The list may get long tho, so I will give your suggestion some thought.
Anyhoo, I do not know how to get the Covers to show up in the CoverView control. Any help is appreciated ! Thank you !
Andy
|
|
|
|
|
Alright, first of all, I think you're making your job bigger than it has to be with the Covers class. It looks to me like you can use a generic list<t> for what you're doing there. This may save you casting as well. Always use generics if they fit your processing concept, because type safety eliminates casting, which results in economy and speed. The only time I don't use generics is when I have an exceptional circumstance which generics cannot conveniently/appropriately handle.
It is not clear from what you've said so far that your concept for accomplishing your goals is sufficiently refined. Are you embedding your collection/list into an outer composite class which will handle your add method? My initial thinking would be to do so; and I would most likely use that class to handle the basic drawing surface. This would also allow you to hide all the internal members you don't want your clients exposed to. The appropriate base class for your project may be Control. You only need to move up the tree for further behavior if you can best take advantage of (or require) prebuilt features such as scrolling provided by a higher, existent class.
This outer class needs to handle adding and drawing by calling into your list. If you need to assign your images to a picture class which can be selected (or which eliminate having to write specialized code to detect object specific events), you need to pick the class on merits decided by the facts it does more of the things already for you than other classes -- without providing excessive functionality that bloats its footprint.
You may have a basic conceptual problem with Parent assignment (next to last line). What you need to understand is your *display* class (PictureBox? or whatever) has to be parented by your display surface (root Control or Panel for instance). You are making your collection item parented by a UserControl instance, but there is nothing here that tells me you have made your collection item a class which can display an image, and you haven't shown any way that an image is assigned to the collection item class, either.
You need to design a basic process to perform these tasks, and generally such a process must go something like this (envision having to manually do what your code has to do, and that will spell out the process to you):
Your base control probably will need an Add method which inserts or appends a new member in your internalized list/collection. You may also provide susupend and resume methods which allow you to add multiple list members and only draw once at the conclusion of mass member propagations.
The add method assigns an image to the list member object. If that object displays your image for you, then your drawing method decides the position of the object and adds it to the controls array of your root object to set Parent. This in effect draws the object (because internalized drawing methods of the base class do this for you). You probably will not want to try to invoke drawing by calling invalidate.
If on the other hand you choose simply to maintain images in the list and draw them directly to the surface (faster and more efficient), then your Add method draws the image to the surface instead of adding an object to the Controls array.
Incidentally, even when you are double buffering, you do not necessarily have to trigger drawing by calling Invalidate() -- and it may be undesirable to rely on Invalidate(). The IDE sometimes ignores calls to Invalidate(), as it does with other calls such as OnEnabledChanged()/OnSystemColorsChanged(), and this of course can lead to frustrating and costly development issues if you rely on Invalidate().
If you assign your image to the background image of an object however (dimensioned and configured to draw only the image), this *will* trigger Invalidate() under all conditions -- so this is perhaps a more robust approach.
So get your process assigning images to members and drawing them. These vitals are missing from your example.
|
|
|
|
|
Mike,
Wow. Thank you very much for such a detailed reply. It will take me a little time to digest it all. I've been making the VB6 -> C#.NET transition for the last 2 months and it's been quite a ride.
My whole intention is to show a sliding list of Album Covers (thumbnails from a database) w text below that I can select. That is about it. Drawing to the surface of a panel for speed sounds like a great idea, as there will be mass populating of the control at times.
Thx again,
Andy
|
|
|
|
|
You are quite welcome.
Personally, I'm not really hot about .NET being the best way to get such jobs done. If you're changing tools, C++ is a really stable career move. Whether it would work best for what you're doing depends on what you're doing -- but frankly, there isn't much that C++ isn't superior for (even if C# is a great step ahead in certain areas such as header-free development).
In any case, your project touches on a number of things I have to do rather regularly. Stress generics (no matter the development tool). Go light with your resource footprint. Much is said here about certain C# drawing techniques (or technologies) being slow, but you can get around that, particularly with double buffering. The usual requisite approach is to draw off-screen first -- then iterate your generic list to get the job done.
|
|
|
|
|
Hello..
Example:
there are 2 textbox, where i'll type a numeric value
this is the value in the first 2 textbox,
textBox1=500
textBox2=1000
then in textBox3 the sum of the 2 values in the textbox should be automatically generated without triggering it with a button.
Example, i just finish typing those numbers and when i'll press tab in my keyboard,
texBox3 should display=1500
how will i code it?
thanks.
|
|
|
|
|
private void textBox2_Leave(object sender, System.EventArgs e)
{
textBox3 = Convert.ToString( Convert.ToInt64(textBox1.Text)+Convert.ToInt64( textBox2.Text));
}
rahul
|
|
|
|
|
The above function is not a correct one... It ll give an error "Cannot implicitly convert type 'string' to 'System.Windows.Forms.TextBox'".
To correct that,
assign the converted string to the textbox3's text.
textBox3.Text = Convert.ToString( Convert.ToInt64(textBox1.Text)+Convert.ToInt64( textBox2.Text));
Thanks & Rgds,
Sri..
|
|
|
|
|
That is just a question of common sense
rahul
|
|
|
|
|
I have a class which descends from Control and features a Bitmap property. It is my impression that it is my control's responsibility to call Dispose() on the example f_BitmapField in the commented out call of the following snippet. If I deploy this call (remove the comment instructions), there is no resource issue at run time destruction, but if this control is placed on a parent control, then when I delete the parent control at design time (without first deleting my child control) I get an ambiguous error stating only that a parameter is invalid. A later dialog is sometimes raised which refers to the property, not the field — suggesting that an invalid reference to the property exists. No Finalize method is deployed, and no further dispose processes refer to the field or resources which can be associated with it at disposal.
Can anybody explain this behavior? Is it not theoretically the control's responsibility to call Dispose() on the bitmap field as in the commented lines here?
I am beginning to wonder if the IDE isn't mishandling the proper implementation — forcing me to write the wrong code (omit dispose) so that I get acceptable design time behavior. Run time behavior doesn't seem to be affected. I don't feel comfortable about the required implementation. Maybe someone knows there is a different, explicit pattern to follow here?
protected override void Dispose( bool disposing )
{
if ( disposing )
{
}
base.Dispose( disposing );
}
|
|
|
|
|
I'm new to learning C# and I don't know what all the error messages mean. Yet. Can somebody give me a clue as to what the following means. And maybe what I need to do to fix it. Thanks in advance for any information.
"An object reference is required for the nonstatic field, method, or property"
|
|
|
|
|
This message means that u r tying to initialize any method or property of a class
with out creating its object u r trying to access it directly through that class
but that class is non static.It is only possible for static class to access its
public methods and property directly with out creating any object.
rahul
|
|
|
|
|
Hey,
I have to compresse 70MB of data in a C# application and I have to mail them automaticaly back to our server. So I have to compresse them in 7 files of 10MB. Is there any way I can do this in c#? I looked everywhere but it's always 1 .zip file you can make
I thank you for your time!
olivier
|
|
|
|
|
|
Hi, .net lets you make as many zips as you want:
http://msdn.microsoft.com/msdnmag/issues/03/06/ZipCompression/default.aspx
|
|
|
|
|
HI,
In C# how do you compare 2 struct's?
Thanks,
Liam
|
|
|
|
|
firstStruct.Equals(secondStruct)
|
|
|
|
|
I guess that depends on how you're going to use them and if the structs are the same type. The IComparer interface is what you'd want to use if you didn't have control of the structs and you were trying to sort them in a list (for example). You could also implement the IComparable interface on the struct if you have control over them.
|
|
|
|
|
You should not use Equals if you want to compare for true equality, because Equals only checks if the compared values refer to the same instance. To determine true equality of value you have to compare the fields. See Richter for further information. The base implementation actually compares for identity, not equality.
|
|
|
|
|
Hi,
I have a table displayed in a datagrid.
If I select a cell, that row has to be populated in the text boxes that I have.
I am unable to refer to the individual fields in the row, of the cell that I clicked.
For EG: If i select any cell in row 10 all the columns in row 10 has to be populated in the text boxes that I have.
Can you please tell me how to refer to the cells in the row that I have selected.
An example code will be very very helpful.
Thanks,Arun
|
|
|
|
|
Try something like this:
DataGridCell dgCell = dataGrid.CurrentCell;
textBox.Text = dataGrid[dgCell.RowNumber, dgCell.ColumnNumber].ToString();
|
|
|
|
|
Hi,
I am trying to find out if there is some function to validate whether a user entered an integer. All suggestions welcome. Thanks.
|
|
|
|
|
Entered an integer into what? A web for then I would suggest javascript validation isNumber (or is it isNumeric I really don't remember) or even the regular expressions.
If it is server side just TryParse.Int32. Also, various styles of input text boxes exist which can automagically restrict input.
File Not Found
|
|
|
|
|
Here are a couple of ideas:
1. You could mask the input and only allow digits:
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (char.IsDigit(e.KeyChar) == false)
{
MessageBox.Show("Invalid Input...");
}
...
}
Of course you would also have to handle the user entering text without pressing a key (a paste operation for example).
2. You can attempt to convert the value when the user is finished:
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
int number;
bool isNumber = int32.TryParse(textbox1.Text, out number);
if(isNumber == true)
// Do something
else
MessageBox.Show("Invalid Input...");
...
}
}
Ian
|
|
|
|
|
When testing one of my programs i got a Loader Lock Message from VIsual Studio 2005:
LoaderLock was detected
Message: Attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.
I did some testing and it occurs whenever I press a key on a program i am testing, even if there is only a form and nothing else. How should I fix this problem? I need this fixed to test my program. Thanks.
|
|
|
|
|
The loader lock detection isn't an actual exception; it's a Visual Studio "debugging assistant" that helps you track down bad practices, leaks, and other workin's of the devil.
First of all, make sure this is valid: are you doing any unmanaged interop during initialization? If so, this error may be valid and you should fix it.
If this isn't a valid error, fortunately for this scenario, you can disable this debugging assistant: Debug->Exceptions->Managed Debugging Assistants->Loader Lock. Uncheck the "thrown" box, and you won't see this error any more.
|
|
|
|