I'm writing a custom control from scratch (using Graphics) that will represent a set of columns each of which will have a list of cells, a lot like a grid view except this will have some custom features.
I'm having a hard time trying to figure out how to manage all the data binding problem. I'd like this grid to have a DataSource property which would basically need to be a jagged array (2D) of some objects each of which would need to be bound to a cell in the control. I'm still not sure which properties each of these objects will have, and so far I'm only using text. What I've been trying to do is have my model implement this interface:
public interface IDiagramDataSource
{
IBindingList Columns { get; }
}
and then have each column implement this:
public interface IDiagramColumnDataSource : INotifyPropertyChanged
{
IBindingList Cells { get; }
}
But I'm still having a hard time figuring out the best way to keep all these objects synchronized to the corresponding objects in my grid. I'd love to be able to put all the binding mess in an independent class but not sure how to do this. For now I'll just repaint the whole thing whenever there is any change in the data source, but I'd like to eventually be able to identify which property in which cell or which cell in which column have changed so that I can update only the necessary items in my grid.
Is there any pattern to follow when you want a control to be bindable to nested lists? I'm guessing there is since the DataGridView control does this.
I would suggest 2 option:
First suggestion has been suggested by HighCore, is to using WPF rather than custom winform object to do the job. WPF also has much more controls (ListView, even the generic ItemContainer, if I am not mistaken). Just implement the INotifyPropertyChanged at the ViewModel, then call OnPropertyChanged for the root (aggregate) element everytime you need to refresh the control. Don't forget to add UpdateSourceTrigger for ItemsSource Binding. WPF controls also has good implementation for drag and drop function.
I won't detail the implementation in WPF since there are much articles explaining it.
However if you think that it must be done with custom graphic drawing, then it is quite complex. You must trigger the method to re-draw your control graphic everytime any changes occured in the item list for it to take effect. It will be better if you can do partial update to your graphic (maybe using panels to trick it), but it is harder.
If not handled correctly (moreover if your control contains huge amount of data and/or control size) then it can causes some high memory loads.
Related
I am having a form with different type of controls like Text Box, Drop downs, Check box, Radio buttons etc. All these controls are loaded dynamically from database at run time.
I want to perform validation on Text box on conditional basis. For example, If we have selected any value in drop down, then you must have to fill details in Text box. Otherwise text box details are not required.
I am open to use database to perform this task and I am using MVVM pattern in my project.
Any help on this is highly appreciated.
Thanks.
(I started this as a comment, but it ended up being too long).
In theory you have access to all these controls and their values in your ViewModel.
Without knowing the specifics of your program, it's difficult to suggest anything useful, but in essence you need to expose some more properties from your ViewModel (probably boolean) which will be calculated based on the values in your controls. Then you need to bind IsEnabled properties on your controls to these new properties.
Sounds simple, but I think you have some architectural problems which will make it difficult to implement what I suggested above. In order for this to work and automatically update your controls whenever other controls' content change, your ViewModel needs to implement INotifyPropertyChanged and raise PropertyChanged event every time you update one of those boolean properties.
I think what you're trying to do could be achieved with ItemsControl and DataTemplates (and maybe DataTemplateSelectors). This will allow you to store "data" in your ViewModel (say List or something more specific) without referencing the actual Controls and the relevant DataTemplates will add the right controls for different data types you have in your ViewModel.
I'm trying to design a WPF application where users can design an algorithm flow chart. This means lots and lots of graphics on my grid. (I was going to use Canvas, but decided to go with grid since canvas doesn't support ScrollViewer natively). I am using MVVM design pattern in my application.
To add/remove graphics dynamically, what states from viewmodel should I export to my view?
As is typical with in all cases where you are going to be displaying a collection of items, you need to:
Create a class that represents each item (i.e. a Model for the items)
Expose an ObservableCollection of this class as a property of your ViewModel
The particulars may vary quite a bit though. I cannot visualize how exactly you intend to implement the view as a Grid, so here are some guidelines assuming it were a Canvas.
Determine your persistence model
When the items are placed on the view, is the user going to be able to move them around? Should their positions be faithfully reproduced if the document is saved, closed and then reopened? If so, then your model for the items needs to aggregate these display parameters. If not, then the view might decide how to position the items itself at runtime.
Use sub-ViewModels if it makes sense
If your item models are very simple then it's possible that you can represent them visually using an inline ItemTemplate for your ItemsControl. If not, then you might want to create an ItemViewModel and expose an ObservableCollection<ItemViewModel> from your main ViewModel.
This is a getting started question about how to create a reusable wpf slideshow control:
that displays a sequence of any visualizable elements e.g. a series of Image controls or a series of UserControls (should I target ContentControl, or is there a broader type that encompasses more visualizables/controls?)
the control should be able to accept an IList of some kind, which would be the elements/slides to present
the control should expose an Interval property that determines the duration of each slide, but i dont even know the basics of how to get started with that in terms of offering that property to be configured in xaml?
and what should the container be, if any, for the individual slides/controls that are passed in?
To start with, you should probably create a UserControl which contains an Image control, and perhaps Next/Previous Buttons, and anything else you may need. These would all be laid out as normal using a variety of panels, you could probably style most of it with just a Grid.
After that, your UserControl will implement the ImageSource (your IList, or IEnumerable of images), and your interval as dependency properties. These are then settable in XAML.
You would then write the logic which loads the next image and sets it as the Image's Source property, this could happen in the change event for the ImageSource property. You can then get as advanced as you wish with Image preloading/caching etc.
I've just delved into WPF myself for a "Slideshow" like project where I'm showing customer order numbers on screen for a period of time before showing the next, and using Effect/Transitions/Storyboards to move to the next frame. I found a good article on CodeProject
I used a Grid with 2 rows:
Contains my "Changing area".
Contains static information (logo, controls etc).
Rememeber to set "cliptobounds = true" on your changing area if you use any sort of transforms on it. (I know you said you aren't using transitions initially, but once people see it, they'll be asking).
Dependency properties are also easily built in C# if you just type propdp and hit tab.
How is data binding in C# WinForms supposed to work when you have a Save button? I don't want the data updated until I press Save!
I have two forms (list and detail) backed by a BindingList<T> collection and my custom object from that collection, respectively. I can bind each form to the list or object appropriately. However, any changes made in the detail form are immediately reflected in the list form - I don't want to save the changes and update the details shown in the list until the Save button is pressed.
Is data binding designed to support this? Is there a common pattern for doing so?
Whichever way I look at it, binding doesn't seem to be able to support this scenario. I've considered the following:
Pass a clone of the object to the detail form, but then I have to reconcile the changes on Save - changes may have been made to the copy in the list in the meantime.
Implementing IEditableObject and calling EndEdit on save almost works as I can prevent the list being notified of the changes made until Save is pressed, but if something else causes a refresh the list is updated with the interim data.
I'm currently left with dispensing with data binding in my detail view, and doing it all manually. Which is rather annoying.
Data binding really wasn't designed for this kind of thing, unfortunately.
The best solution we've found here is to edit object clones, then reconcile the changes, as you mentioned. You may want to come up with a custom collection and/or object interface that helps you manage this type of thing.
Even if the cloning method is slightly more work up front, it's going to be wayyyy less complicated and frustrating than using IEditableObject trying to catch all the possible events that update the data. Not only that, it's a more straightforward approach, and you won't end up with spaghetti code.
If you are set on using a binding list, your best bet would be to implement IBindingList to create the functionality that you desire. It may also be possible to pull this off by simply inheriting from BindingList and overriding the appropriate methods to change the binding list's behavior.
http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.aspx
If you are not set on using a binding list, it is probably best to do the data manipulations manually based off of the control's events.
Best of luck.
I've adopted the following pattern for putting ListViewItems in a ListView with multiple columns (when I want to display information about a list of MyObject types), and I'm just curious to see if this is the best way to accomplish this task, or if there's anything more efficient and readable in code:
Create an inherited ListViewItem class that takes a MyObject object in the constructor - I'll call this MyObjectListViewItem - and a Refresh() method that clears and re-populates the ListViewItem subitems.
Populate the ListView with my new MyObjectListViewItem items.
example:
public MyObject MyObject { get; set; }
public MyObjectListViewItem(MyObject myObj)
{
MyObject = myObj;
this.Refresh();
}
public void Refresh()
{
this.SubItems.Clear();
this.Text = myObj.FirstColumnProperty;
this.SubItems.Add(myObj.SecondColumnProperty); // etc...
}
Suggestions? Better ways?
Have you considered using a BindingSource, or creating your own which implements IBindingListView? This keeps concerns about the data and its state scoped to the data itself and not on any controls which consume it. Since .NET controls are already built to work with BindingSources, you can take advantage of some more robust functionality. Instead of explicitly invoking a screen refresh, the control is simply responsible for responding to events raised by the binding source, and a controller that notifies whether the control is ready to be refreshed without forcing it.
Making ListViewItems that know how to build themselves is a good idea.
If you extend that idea a little, you make the columns know how to build each subitem, which also allows them to be able to automatically sort the ListView, support grouping and copy/drag and drop rows. This is just a few of the things that ObjectListView does for you.
ObjectListView is an open source wrapper around a .NET WinForms ListView control that makes the ListView much easier to use -- as well as adding some very nice new features and getting around some annoying bugs/limitations.
If you did like #Rex's idea of using a BindingSource, the ObjectListView project also provides a data-aware DataListView which is data bindable.