|
macantony wrote: I am not too sure where to start
By reading the article I linked; it explains how to program against the Agent API.
macantony wrote: I have looked at some articles but I still am confused.
Well, if it's something specific that you're confused about then we can look into that. If the concept is still vague, then you'd have to follow one of the articles from top to bottom.
Programming an agent isn't explained with a few code-snippets, but you could have a nice result in a few days if you follow the article.
Bastard Programmer from Hell
|
|
|
|
|
Note 1: I just became aware of Luc Patyn's very interesting article: "WinForms AutoScroll Experiment"[^], and am diligently studying that code to see if it would meet my needs in this scenario.
Note 2: I thought about posting this on the WinForms forum, but that forum doesn't see much action, and, I consider it vaguely possible that a similar problem may occur in WPF/SilverLight (poor excuse ?).
Imagine you have a large Panel that fills most of a Form, the OuterPanel: at run-time you are creating/adding Panels into the Controls collection of the OuterPanel, and they are Docked Left. You put a custom drawn border around these inner Panels.
And, you have the auto-scroll property of the OuterPanel set to 'true.
At the point where a new inner Panel is added that exceeds the visible extent of the width of the OuterPanel, the Horizontal ScrollBar will automatically appear.
Unfortunately the H-Scrollbar appearing also reduces the vertical internal size of the OuterPanel's effective display area by about 17 pixels, which can result in the bottoms of your docked inner Panels being 'clipped' out of view.
I have a work-around for this based on detecting the change in the OuterPanel's size, and then just increasing the OuterPanel's height by 17 pixels, but that's ... errr ... not very elegant, since you've got a visible "bump" in the UI. I suppose I could enumerate the inner Panels and shrink their height, also, but I find that equally revolting a thought
The beauty of using Docking is the auto-alignment and re-sizing you get, the downside is you eliminate the other nice features provided by the 'Margin and 'Padding properties of controls.
I would love to have a set of DockedMargin and DockedPadding properties that paralleled the Margin and Padding properties for undocked controls !
I assume there is, but haven't tried to find, some pInvoke that could force a Panel to always show the horizontal scrollbar. I'd consider that a "last resort."
Any ideas ?
thanks, Bill
Scipio: "That's true, Berganza; and what makes the miracle greater is, that we not only speak, but hold intelligent discourse, as though we had souls capable of reason; whereas we are so far from having it, that the difference between brutes and man consists in this, that man is a rational animal, and the brute is irrational." Cervantes, "Colloquy of Dogs," 1613CE. The two talking dogs, Scipio, Berganza, are hallucinations in the mind of a soldier with plague fever undergoing a "sweating" cure.
modified 27-Nov-11 9:14am.
|
|
|
|
|
Who needs pInvoke?
myPanel.HorizontalScroll.Visible = true;
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
How I wish this would work ! In my innumerable experiments I found:
1. if AutoScroll is set to 'true, setting both Visible and Enabled properties of somePanel.HorizontalScroll will have no effect.
2. if AutoScroll is set to 'false: yes, the HorizontalScrollBar can be forced to appear, as you show, but does not move the Panel when scrolled, at least not in my OuterPanel, which is completely filled at any moment in time with Docked inner Panels.
So, okay, you implement the Scroll Event, and as I drag the scroller, I can monitor the changing values of its position: they are changing.
But, when I mouse-up on the scroller, after moving it: it snaps back to far-left position in the scrollbar, and the Panel is not scrolled at any time !
I also tried, in the code in the main Form that creates a new inner Panel, and inserts it in the OuterPanel, calling:
OuterPanel.ScrollIntoView(newInnerPanel);
OuterPanel.Invalidate(); No result, there, either.
Which is why I did not pursue use of the Scroll event, or ScrollIntoView.
I appreciate your response, and perhaps I should re-direct my attention to: when a new inner panel is added, calculating where its right border is in OuterPanel co-ordinates, and trying to somehow force the horizontal scrollbar position so that the newly added inner Panel is fully visible ?
But, will "forcing" the h-scrollbar scroller position require a pInvoke, and/or actually move the Panel ? mmmm ...
At least when AutoScroll is set to 'true, and the scrollbar appears, the Panel will be moved when you move the scroller.
Looking forward to your continuing exercise of your (greatly admired) skills in finding the 'blind spots' in code.
thanks, Bill
"Anyone who shows me my 'blind spots' gives me the gift of sight." ... a thought from the shallows of the deeply shallow mind of ... Bill
|
|
|
|
|
Hey - you only said you wanted it to show the horizontal scroll bar!
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
One bullet to add to the forum guidelines: don't make your answer way shorter than the question was, right or wrong, it is just too discouraging for the enquirer...
|
|
|
|
|
So "Yes." is out of the question then?
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
indeed.
|
|
|
|
|
I am sure it is only the transferred "psychic force" (mana, shakti) of OriginalGriff just appearing in this thread that led me to go back and take another look at the 'Scroll event of a Panel.
And, shiver me timbers with a cold wind of chagrin: turns out
OuterPanel.HorizontalScroll.Value = e.NewValue; And: voila: as Galileo's final words said: "E pur si muove:" 'and yet, it moves.' The Panel scrolls !
From here, I think it should not be difficult to achieve what I want.
I still wonder about what 'ScrollIntoView, for a Control in a Panel requires to work, however.
One less blind spot for Bill, one small crawl for mankind.
thanks, Bill
"Anyone who shows me my 'blind spots' gives me the gift of sight." ... a thought from the shallows of the deeply shallow mind of ... Bill
|
|
|
|
|
|
I was doing data visualization in C# about a year ago and didn't come across anything like that. Good luck searching but there definitely wont find anything like that out of the box.
"You get that on the big jobs."
|
|
|
|
|
..... really no one knows ="= who can help me ~
|
|
|
|
|
The key is the "viewing transform" that transforms 3D coordinates into (X, Y) coordinates on your computer screen.
You supply the parameters that define your "window" into the 3D world (viewer origin, direction of view, etc). These parameters are used to construct the viewing-transform matrix.
Unfortunately most descriptions of this seem to have unnecessary complexity. Google "viewing transform" and take the easiest one to implement. Ignore the complex derivations, and just use the viewing-transform matrix at the end.
If you do it yourself, you'll also have to supply the coordinates of any letters you use for labeling in 3-space. A simple approach is using an existing 3D graphics package. There are probably a bunch of them on Code Project.
|
|
|
|
|
Alan , thank for your guide. i'll try to google the viewing transform .
Thank you very much .
|
|
|
|
|
How can i convert the IEnumerable<string> to Datatable.
i have this method but it will be slow in large data.
<pre lang="c#">
public static DataTable AsDataTable<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
{
throw new ArgumentNullException("enumerable");
}
DataTable table = new DataTable();
if (enumerable.Any())
{
IList<PropertyInfo> properties = typeof(T)
.GetProperties()
.Where(p => p.CanRead && (p.GetIndexParameters().Length == 0))
.ToList();
foreach (PropertyInfo property in properties)
{
table.Columns.Add(property.Name, property.PropertyType);
}
IList<MethodInfo> getters = properties.Select(p => p.GetGetMethod()).ToList();
table.BeginLoadData();
try
{
object[] values = new object[properties.Count];
foreach (T item in enumerable)
{
for (int i = 0; i < getters.Count; i++)
{
values[i] = getters[i].Invoke(item, BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
}
table.Rows.Add(values);
}
}
finally
{
table.EndLoadData();
}
}
return table;
}
|
|
|
|
|
Hi All !
I have Two List Box , ListBox1 And ListBox2 , there are these Items for e.g.:
ListBox1[0]-->"City One" ---------------- ListBox2[0]=2500
ListBox1[1]-->"City Two" ---------------- ListBox2[1]=3000
ListBox1[2]-->"City Three" ---------------- ListBox2[2]=1500
I want to Sort ListBox2 , And The same Time all Items In ListBox1 Change (Based on ListBox2)
How Can I do it !
Thanks for Any Help
Regards !
|
|
|
|
|
Please clarify what you are trying to accomplish. It isn't very clear, at least to me.
No comment
|
|
|
|
|
The question is not clear.
Two hints nevertheless:
1. ListBoxes (anc ComboBoxes) can do much more than hold strings; you can store any kind of object in there, i.e. show some text (maybe their ToString result) but also contain a lot more information, which might define their sorting order.
2. There are all kinds of ways to get a collection sorted; here[^] is an overview I created.
|
|
|
|
|
Excuse Me !
See Here :
ListBox1.Items[0]-->"City One" ---------------- ListBox2.Items[0]=2500
ListBox1.Items[1]->"City Two" ---------------- ListBox2.Items[1]=3000
ListBox1.Items[2]-->"City Three" ---------------- ListBox2.Items[2]=1500
When I sorting ListBox2(by Number) , I want To Change ListBox1 (by the Index of ListBox2) Like these :
ListBox1.Items[0]->"City Two" <----------------> ListBox2.Items[0]=3000
ListBox1.Items[1]-->"City One" <----------------> ListBox2.Items[1]=2500
ListBox1.Items[2]-->"City Three" <----------------> ListBox2.Items[2]=1500
Thanks
|
|
|
|
|
If I understand you correctly (you are still only spending one short sentence to "explain" things!), I think you're best approach would be:
1. to have a class City with properties for Name, SomeNumber, and maybe more.
2. have one, not two, collections of such City instances; the collection lives outside any ListBox (as the cities do). A List<City> would do fine as collection here.
3. sort that collection any way you choose. My article explains how.
4. have a ListBox that shows the SomeNumber property of said collection. Databinding could do that for you (set DataSource and DisplayMember, and that is why City needs properties).
5. have another ListBox that shows the Name property of said collection. Databinding again.
|
|
|
|
|
my English is not Good
my item in ListBox2 is 3 and is Only Number field :
as I said :
ListBox2.Items[0]=2500
ListBox2.Items[1]=3000
ListBox2.Items[2]=1500
Also the Items for ListBox1 is 3 but String Field , Like these as I Said :
ListBox1.Items[0]-->"City One"
ListBox1.Items[1]->"City Two"
ListBox1.Items[2]-->"City Three"
--------------------------------
in fact my project is about Population , in ListBox1 , we Name of City and in ListBox2 is Their Population :Like these ,
City One =2500
City Two=3000
City Three=1500
Now When I Want To sort ListBox2 , Also ListBox1 should be Sorted .
thanks for your patient
Regards!
|
|
|
|
|
My earlier reply stands.
You should not put just strings in a ListBox, if the population numbers were 10000, 3000, and 1000 you would never get them sorted properly using strings.
|
|
|
|
|
But We have "Two" ListBox, ListBox1 for City And ListBox2 for their Population
Regards!
|
|
|
|
|
I interpret your question as:
Given two List Boxes:
1. where initially ListBox1 is sorted by some criterion (alpha-numeric ?)
2. where initially each ListBox2 item is associated with the item in ListBox1 with the same index (even though they may "appear" unsorted).
Then:
1. in the case where you sort ListBox2 by some criterion
2. you want the items in ListBox1 to remain in matching ordinal position with their "associated" items in ListBox2.
What's "missing" from the picture ... but we can "guess" at ... is if you always are going to sort ListBox2 the same way: we assume here that you are not sorting by just setting
ListBox2.Sorted = true; Which will give you an alphabetic ascending sort. Your example result shows a sort of ListBox2 in descending order.
Since ListBox Items are all strings, there is the question of whether you really want to sort the Items in ListBox2 as strings or as numbers.
Solution ?
1. abstract away the data and associations from the ListBoxes:
a. I'd do this with a Dictionary<string, int> : why use string as the Key: because it's unlikely you'd have two identical city-names, but, perhaps, very possible, you'd have identical population ?
2. On Form Load, or whatever, populate this Dictionary with the CityName-Population data.
3. Create a function that populates the ListBoxes based on enumerating the Dictionary<string, int>
4. Create a function that sorts the Dictionary by Value (strings) in descending order: Dictionary + Linq will do this for you.
Example code:
private Dictionary<string, int> PopCityDict;
private void Form1_Load(object sender, EventArgs e)
{
PopCityDict = new Dictionary<string, int>
{
{"City One", 2500},
{"City Two", 3000},
{"City Three", 1500}
};
InitializeListBoxes();
}
private void InitializeListBoxes()
{
listBox1.Items.Clear();
listBox2.Items.Clear();
foreach (var kvp in PopCityDict)
{
listBox1.Items.Add(kvp.Key);
listBox2.Items.Add(kvp.Value);
}
}
private void SortDescendingButton_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
listBox2.Items.Clear();
foreach (var kvp in PopCityDict.OrderByDescending(criterion => criterion.Value))
{
listBox1.Items.Add(kvp.Key);
listBox2.Items.Add(kvp.Value);
}
} Discussion: The sort will not change the underlying structure (order) of the PopCityDict Dictionary ! Which means to reset the ListBoxes to their original order you can just call
InitializeListBoxes(); If you really want to re-arrange the actual order in the Dictionary: have fun
... edit #1 ...
You could easily implement any number of sorting modes by making a more general-purpose sort routine where the OrderBy#.... Linq method used on 'PopCityDict was chosen based on an input parameter to the sorting routine.
And use of a Dictionary is, I am sure, only one option; you could probably use a List of Tuples, etc.
... end edit #1 ...
Scipio: "That's true, Berganza; and what makes the miracle greater is, that we not only speak, but hold intelligent discourse, as though we had souls capable of reason; whereas we are so far from having it, that the difference between brutes and man consists in this, that man is a rational animal, and the brute is irrational." Cervantes, "Colloquy of Dogs," 1613CE. The two talking dogs, Scipio, Berganza, are hallucinations in the mind of a soldier with plague fever undergoing a "sweating" cure.
modified 27-Nov-11 8:25am.
|
|
|
|
|
There have been several things suggested but you don't seem to be understanding it, I'll try to help.
You seem to be getting confused about how much data you have. You only have ONE collection of cities, you just happen to be showing the individual bits of information (name, population) on two seperate controls. The first thing to do is to get your information into one City class and provide methods for sorting based on name or population - something like:
public class City
{
public const int MinPopulation = 0;
public event EventHandler PopulationChanged;
private string name;
private int population;
public City(string name, int population)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name", "Name cannot be null or empty");
if (population < MinPopulation)
throw new ArgumentOutOfRangeException(
"population",
string.Format("Population cannot be less than {0}", MinPopulation));
this.name = name;
this.population = population;
}
public string Name
{
get { return name; }
}
public int Population
{
get { return population; }
set
{
if (value < MinPopulation)
throw new ArgumentOutOfRangeException(
"Population",
string.Format("Population cannot be less than {0}", MinPopulation));
population = value;
OnPopulationChanged(EventArgs.Empty);
}
}
protected virtual void OnPopulationChanged(EventArgs e)
{
EventHandler eh = PopulationChanged;
if (eh != null)
eh(this, e);
}
public static int CompareName(City first, City second)
{
if (object.ReferenceEquals(first, second))
return 0;
if (object.ReferenceEquals(first, null))
return -1;
if (object.ReferenceEquals(second, null))
return 1;
return first.name.CompareTo(second.name);
}
public static int ComparePopulation(City first, City second)
{
if (object.ReferenceEquals(first, second))
return 0;
if (object.ReferenceEquals(first, null))
return -1;
if (object.ReferenceEquals(second, null))
return 1;
return first.population.CompareTo(second.population);
}
}
Now you can keep a collection of cities somewhere (perhaps a List<City> ). You can then use that list as a common DataSource for both of your ListBox es, using the DisplayMember property to choose which property to display. The rough code below needs a button adding buttonSort (with suitable width) for changing the sort.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
public partial class FormMain : Form
{
private const string SortByNameText = "&Sort by Name";
private const string SortByPopulationText = "&Sort by Population";
private List<City> cities;
public FormMain()
{
InitializeComponent();
cities = new List<City>();
BuildCityList();
listBox1.DataSource = cities;
listBox1.DisplayMember = ("Name");
listBox2.DataSource = cities;
listBox2.DisplayMember = ("Population");
buttonSort.Text = "&Sort by Name";
buttonSort.Click += new EventHandler(buttonSort_Click);
}
void buttonSort_Click(object sender, EventArgs e)
{
if (buttonSort.Text == SortByNameText)
{
cities.Sort(new Comparison<City>(City.CompareName));
buttonSort.Text = SortByPopulationText;
}
else
{
cities.Sort(new Comparison<City>(City.ComparePopulation));
buttonSort.Text = SortByNameText;
}
listBox1.DataSource = null;
listBox2.DataSource = null;
listBox1.DataSource = cities;
listBox1.DisplayMember = ("Name");
listBox2.DataSource = cities;
listBox2.DisplayMember = ("Population");
}
private void BuildCityList()
{
cities.Add(new City("City One", 2500));
cities.Add(new City("City Two", 3000));
cities.Add(new City("City Three", 1500));
}
}
|
|
|
|
|