I'm currently trying to develop a small finance application. My application needs a quite complex GUI (basically a table with dynamic rows and columns as well as categories and subcategories); since I couldn't think of a standard xaml-way to achieve that, I'm writing a custom control that is supposed to display my data.
So long story short, I'm creating a lot of different WPF UI elements in C# code directly, not in XAML. Now I'll need a way to synchronize some of these component's values with dynamically changing data. An obvious example is that some of my text boxes (or labels or whatever) will need to display the price of a stock. It should thus be bound to another class which provides up to date prices.
My main problem is that I don't know in advance which prices will be needed and where they should be displayed. So what I'd need is basically a way for my textbox to contact my price-object and ask "hey, i'm going to need a price for stock US0123456789. Please tell me that price and keep updating my value whenever the price of that stock is updated."
All databinding examples I found were usually focused on binding to the variables within a specific object instance, but I can't simply bind to, say, PriceObject.Price because there can't be a simple "Price" variable. After all, there's going to be various different stocks managed by the price object and each text box only needs the price of one specific stock, so it'd need to bind to something like PriceObject.PriceForStock("US0123456789"). I couldn't find a way to bind to a method, though, and I don't know how how else it'd be possible.
The only way I could think of was to have a Dictionary in my GUI-class witch stock ISINs as its keys and a reference to the UI Element as value. Then my GUI could observe the Price Object and each time prices change, and event is triggered and the GUI class could update the UI Element manually, something like (pseudo code incoming):
private Dictionary<string, UIElement> displayed_stocks = new Dictionary<string, UIElement>();
private void create_gui()
{
Textbox textbox = new Textbox();
displayed_stocks.Add(isin, textbox);
}
private void receive_change_event_of_price_object(string affected_isin, double new_price)
{
displayed_stocks[affected_isin].Text = new_price.ToString();
}
But I don't know, I feel like this is a sloppy solution. Especially because I won't only need dynamic prices but also other dynamic information like portfolio holdings, which will rely not only on ISIN but on ISIN and portfolio ID, so it wouldn't be that simple with a dictionary. Is there any better way to do it? I'd be glad to be pushed in the right direction there!
Thanks
If you create an indexer on the object you bind to you can bind with a parameter in a clean and easy manner, see this link for more information.
Dynamic Bindings are achieved using...
Indexer as Bas has already said above. Even ToString() can do the trick too.
MultiBinding with IMultiValueConverter deciding which binding source(s) should take effect. MultiBinding has an advatnage that you can bind all possible things that can be displayed in your TextBox and send them to the converter (whether available or not) and then the converter will decide which one to mould and display.
If the sequence of priority of source values is fixed then you can use PriorityBinding. No need for the converter discussed above.
Related
I have two doubts about the autocomplete feature of textboxes in C#.
First, I want to display the full list, not only the ones that start with the given text, and secondly I want to prevent the auto-complete of specific options (some are category titles).
I've been checking the textbox properties and there's nothing related to it, so probably the main question could be, Is there a way to modify / override the textbox events in order to handle the auto-complete actions? (I don't know if it applies to show the full list too)
I assume you're asking about a winforms textbox, as I dont think the WPF textbox supports autocomplete at all.
The base TextBox class will not support doing what you want, so you could in theory attempt to override all of the functionality in the TextBox class to do what you want, but the better idea would be to create a new custom control that inherits from TextBoxBase and implement the autocomplete behavior the way you want it.
I'm not sure about displaying the full list (perhaps a combobox or similar is more suited to this?) but you can definitely do something like this to swap which list of possible items can be displayed.
Another option, though one I like less, is to remove items you don't want to display at a given time from the collection dynamically, like this: textBox.AutoCompleteCustomSource.Remove("ACategoryTitle")
I could foresee that approach having many problems with trying to rebuild the list constantly. I would probably create a subclass of AutoCompleteStringCollection that wraps some LINQ code to nicely select the union of some lists and not others to display in the textbox.
I decided to build my own autocomplete tool with the help of a simple listbox and events, then I could achieve what I was expecting..
The CodingGorilla's answer probably leads to a better solution if you want something more decent, in my case for speed reasons I decided to do it that way but I'll mark his answer as the accepted in order to help other people who have the same doubt and they could consider that point..
So it seems like what I want to do should be straightforward, but I haven't been able to find a way to do it...
I need to display a list of objects that represent custom elements for entering data. Exactly how each object is displayed depends on the parameters of the object - so it could be a grid containing a name, description, and text box. It could be a grid with a couple labels and a dropdown. It could be an expander that contains multiple sub-objects. It could be something new that hasn't been built yet (so it needs to be extensible). Right now, I am populating this list by creating the FrameworkElement for each object and then adding it to a Grid by hand.
I would like to switch to keeping my objects in an ObservableCollection, and then binding that collection to a ListBox (or similar). That way, when new objects are added or removed from the list, the UI would automatically update itself accordingly. What I can't figure out is, is there a way to point it to my C# method for creating the custom-configured FrameworkElement for each object, so that when new objects are added the appropriate elements will be added to the UI?
Well, you're on the right track as far as wanting to use an ObservableCollection<T> and a ListBox control. Though, I'd venture to say you might want to simply use an ItemsControl since you probably don't care about selecting a particular item, but merely displaying an enumeration of items, and the ListBox would allow you to actually select one of those items.
Your problem is that you want each item in the list to display differently depending on certain criteria. For this you'll want to look at the DataTemplate and DataTemplateSelector classes.
Basically, a DataTemplate is a way of saying "I want my item to look like this.", and a DataTemplateSelector is a way of saying "I want to select this specific DataTemplate based on this criteria."
Here are a few examples on how to use the DataTemplate/DataTemplateSelector classes:
http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector
http://mikestedman.blogspot.com/2009/04/datatemplateselector.html
http://wpftutorial.net/DataTemplates.html
Seperating the presentation from the model is always a good idea. It seems like you are on the right track.
Foreach object type, you should create a DataTemplate and then use ItemTemplateSelector to select the correct template for each object type.
Good luck
I'm writing a program that functions as an Excel-style dictionary. Basically, it allows the user to add rows, edit rows, search through them, and so on. I use it for storing and studying vocabulary for foreign languages.
I've gotten a version up and running that I'm quite happy with. It uses a BindingList as a data source for a DataGridView in order to track changes and record them back to the BindingList that I use to store all the vocabulary, and the list itself is made up of a custom class I named "Term", that has properties for "English Word", "Spanish Word", "Examples", ect. What it doesn't do is let the user customize the fields, and that's where my problem comes in. It's pretty much "hard-coded" in that even if I'm studying Spanish or French, the Term class is going to be using the property for "Kanji" from Japanese.
I want to be able to have the user type in what fields they want the dictionary to display and keep track of--basically, they should be able to rename and add/remove columns from the DataGridView. My first thought was to implement this as a List, which stores the names of the fields (and accordingly the number of them, by using the List's length). Then, I would have a Word class that has a List property, and each string in the list represents one of the fields. Then I create a BindingList of this Word class, which leaves me with a BindingList of Lists.
When I try to databind my List list to my DataGridView, the grid comes up empty--it apparently has no idea how I want the data to be displayed and I'm having great difficulty figuring out how to tell it to. I'm not even sure if my approach of having a List of Lists is a good way to implement customizable fields, but it's the best I could think of. In any event, can anyone recommend a way to approach this that lets me add the fields to the table, but also tracks changes and pastes them back to the original source? I need the grid to be used as an editing tool for the user to not only add new elements, but also change existing ones.
It's a personal project, but it's driving me a bit crazy. I was up until 5AM last night trying to figure it out and came up empty-handed. Thanks very much for reading!
I've read your post a couple of times. I'm not sure I understand completly. If I don't, please give some details and I'll try to help.
If I had to do a Excel-like DataGridView, I think I'd use an Array. I would create an array of, say, 256 by 256 and put it as DataSource. Then after the user edits, you read the whole DataGrid and rewrite if it differs from the array you originally had.
I think you might be interested in this class:
http://www.codeproject.com/KB/grid/DGVColumnSelector.aspx
It allows the user to dynamically display which columns are shown in the DataGridView
I have a class that returns a list of "Category" Objects. I'd like to display them along the left-hand side of the page in a listview (if that's the best way to do it, even).
The category objects have normal attributes. Title, User, NumberOfProjects. I'd like to display both the title and the number of projects in this list.
Not worried about editability right now as we might make that separate (i.e. not in-line in a list view edit mode).
What do you think is the best way to do this?
Thanks in advance for any help you can give! :)
First if the array of the objects is too big I'd recommend to use virtual mode of ListView.
Second, nice way to "convert" youur object to string is to override ToString method where you can represent info of your object.
One alternative is to bind your collection to a DataGridView and display that, which would save you having to load each item manually but looks tacky and like it was made in Access.
Personally, I'd use a list view as you've suggested. I find that although you have to load its items manually, its simple and looks by far the most professional.
I was just looking for the best way to use a ListView control, I suppose.
I was able to figure it out -- I wasn't using correctly and hadn't included a "contentPlaceholder" element.
After doing this, I was able to use <%#Eval("FieldName")%> to insert the object's properties into labels. It was already in list format, so the databind was a snap.
If code would benefit anyone else, I'll post it -- I just didn't feel like cutting out all the extra CSS. ;)
Thanks to everyone who tried to help with this!
I am pretty new to C# and .NET and I'm strugling a little with the whole concept of databinding. What I am asking for is a quick rundown of the concept, or even better, point me towards sources on the net (preferred) or in print that can help me get my head around the idea.
EDIT:
I do my development in vs2008 and we are using winforms
Well, what architecture are you using? winforms? asp.net? wpf?
The high level is that if you have objects such as:
public class Person {
public string Name {get;set;}
public DateTime DateOfBirth {get;set;}
}
Then you can get the binding framework to do all the hard work, and you just say what you want bound - for example (winforms):
txtName.DataBindings.Add("Text", person, "Name");
This sets the textbox's Text property based on the person's Name, and can update the person's Name when the user changes the text.
Multi-record binding is more complex, and is based on IList in winforms/wpf, and IEunmerable in ASP.NET; this allows you to bind multiple records (for example into a grid). If the list offers extra features (sorting, filtering etc, via IBindingList, IBindingListView, etc), then more functionality might be available.
Binding also allows "observer" usage - i.e. change notification: if you indirectly change the person's Name, then the textbox gets automatically updated. This relies on events - either of the form public event EventHandler NameChanged;, or (more commonly now) via the INotifyPropertyChanged event (allowing one event to notify for multiple properties).
Some lists (such as BindingList<T>, DataView) have similar notification loops.
The concept of databinding is quite simple;
It allows you to 'bind' the data that is contained in an object to a visual control.
That control 'displays' your data. When the user changes the value that is displayed by the control, the changes are automatically persisted to the underlying object.
Vice versa, when someone changes the data in the object, the control can display the newest value.
http://msdn.microsoft.com/en-us/library/ms752347.aspx
http://www.akadia.com/services/dotnet_databinding.html