I have a network service that provides a number of key-value pairs. The collection is huge and the available keys are changing over time. My goal is to be able to bind to this collection in either Visual Studio 2013 or Blend using the properties window in design mode (or intellisense in XAML). This of course requires the service client object to somehow be initialized during design mode to connect to the service and expose the keys as bindable properties.
I have been searching a lot about "ObjectDataSource" but my problem is that I cannot dynamically change the properties of this object.
What type of object should I choose as my data context?
How can I populate it during design mode?
Any ideas or suggestions towards how this could be implemented would be great.
You can set your data context to any object - you get dynamic updates if
the object implements INotifyPropertyChanged (http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx)
or is observable (like ObservableCollection<> (http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx)).
If your goal is to create an observable dictionary, have a look at this post: http://blogs.microsoft.co.il/shimmy/2010/12/26/observabledictionarylttkey-tvaluegt-c/
The object data provider can have it's data source set to any object too - the dynamic updates will occur if the object is as stated above. In addition, you can declaratively set the objectDataSource's values in xaml - but this doesn't appear to be something you want to do.
Note: You don't change the properties of the object data source - you change the object that it is wrapping for you.
If you want to be able to control the selected item of something like a list (a bit like the Winforms BindingSource)- take a look at ICollectionView (http://msdn.microsoft.com/en-us/library/system.componentmodel.icollectionview(v=vs.110).aspx) which can be created by wrapping up your actual data source (same observable rules apply to get dynamic updates) using CollectionView (see http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.getdefaultview(v=vs.110).aspx)
So - to answer the rest of your question, one solution is to create an observable collection of observable objects (wrapping your key value pairs) and set that as your data context (or set it as your objectDataProvider's source, and bind your Xaml accordingly. This isn't the only way, but a quick google will show you others.
Edit Design mode
For design time data - look at using the design mode flags - an example is here: http://www.arrangeactassert.com/how-to-use-designdata-to-populate-controls-with-design-time-data-in-silverlight-and-wpf/
A list of (Silverlight design time attributes): http://msdn.microsoft.com/en-us/library/ff602277%28v=vs.95%29.aspx
I've never actually tried the design time stuff, so that's all I got!
Hth.
Related
I want to create a class and its properties on run time, the properties will be like Year2001, Year2002, Year2003, Year2004, Year2005... I get these property names on run-time, I get them in a list. Later I need to use this class to create a list which I need to show in the kendo grid.I surfed a lot and thought of using ExpandoObject, but was unsuccessful.
If all properties will be of the form YearX and contain some information about or related to that year, then I would strongly recommend you (if at all possible) to go with something along the lines of an IList<YearInfo> where YearInfo is some object containing the info you need for every year, including an integer property indicating what year the object corresponds to. If you require these objects to be unique you could use an IDictionary<int, YearObject> or ISet<YearObject> instead.
Reflection can be powerful, but it it comes at the price of complexity and loss of type safety/compile-time checks. Avoid when possible.
Sounds to me like you are really wanting to a grid with grouping support. Your idea of having the system create a CLASS at runtime is not going to fly. Even if it were possible, which I doubt it is, it is absolutely the wrong approach.
Like I say - have a read about Grouping / Hierarchy on Grid Controls (Kendo grid example here), and maybe have a look at OLAP cubes as well...
Although you have had some answers I would also like to suggest an alternative way of doing this which is using DataTables. This is the approach I take when I have any "Dynamic" data sets that I want to present to the grid.
This is also the approach that Telerik themselves take with one of their code samples.
here are a couple of links to show them doing this to DataTables and Dynamic Objects
Grid Binding to Data Table
Grid Binding to Dynamic Objects
Personally I find the binding to Tables easier to deal with as I am used to dealing with Data Tables.
I have a case where in the columns of Datagrid are not fixed . i.e it has to be generated depending on some conditions.
How can i store the values in the DB and display the datagrid with them using MVVM pattern.
P.S : I have a main grid and a sub grid and depending on the value he chooses in the main grid i need to form the below grid. My concern also in storing it in the DB, since there can be 5 columns or sometimes 20.
Any similar links or references will also be useful.
This can be totally done in an MVVM compliant way, but isn't necessarily trivial for a beginner, and isn't appropriate for simple applications.
One approach I like to use is to keep a collection of column descriptors serialised in the database1. The column descriptors are simply my own custom DTO data classes and contain properties related to a column, i.e. width, column type, whether it is visible, whether it's visibility can be toggled, it's ordinal, etc. This is all done using simple structs and or primitive .Net types, but specifically doesn't have any UI related data types in it at all2.
This list of ColumnDescriptors can then be serialiased to and from XML, and stored in the database either in an nvarchar or XML column. Especially on SQL Server an XML column is better as you can natively query deep into the XML structures stored in the database column.
As it is a UI layout thing, it is up to the view to query the right set of column descriptors from the database, I then pump that collection through a static GridColumnFactory class which iterates the descriptor objects and creates me the appropriate grid columns and assigns the appropriate values to them. Once the factory returns that collection the view can then add them to the DataGrid's columns collection.
The benefits of this approach:
If I swap out the DataGrid that is used (i.e. swap from one vendor to another, say DevExpress to ComponentOne or native WPF), I can simply change the types of columns returned from the factory class
If I swap anything in the UI then I don't need to touch the column descriptors that are stored.
Serialising to and from XML means that if I do add/remove properties from the descriptors then older stored copies can still be accommodated, they aren't instantly broken the moment I release an update
One of the best features of all is that I can change the stored column layouts with a simple SQL statement, I don't have to also release compiled code
One last thing - using column descriptors makes it trivial to implement a user specified layout, i.e. when you let them drag columns around and then want to save the layout for next time
If I want to get really funky, the column descriptors can be returned from a webservice
1 For a website these could also be stored in a loose XML file which is then read in and kept in cache.
2 For this approach you should always avoid using specialised or vendor specific data types, as they don't necessarily serialise well (if at all), and will become a weak point in the future - these will be the most likely things you have to change, and if these change you break any stored descriptors you've already got.
I am new to the MVVM-pattern, and am trying out Caliburn.Micro on a project.
I want to have one ViewModel (which contains a collection of ViewModels) shared by multiple Views, where each view only displays items which have a certain value on one of it's properties.
To get specific, I am using a service which allows me to monitor different values that update frequently. I then get an object of type MonitoredItem, which contains a property of type DataValue, which in turn contains an object for the Value and a property for the value's datatype.
So far I have a MonitoredItemViewModel which uses this service's MonitoredItem class as it's model, and a MonitoredItemsViewModel which contains BindableCollection<MonitoredItemViewModel> MonitoredItems, and commands for adding/removing items.
I also have a MonitoredItemsView where I can see all the items I am currently monitoring.
How do I go about splitting up the view, so that I can have all MonitoredItems where DataValue is an integer/float/double displayed in one area in my window, boolean values displayed somewhere else etc?
Don't do it in the view, instead expose different collections on your ViewModels according to what you need to filter.
This can be done either as known collections, e.g.
public ObservableCollection<MonitoredItemViewModel> ItemsWhereFooIsBar ...
public ObservableCollection<MonitoredItemViewModel> ItemsWhereFooIsntBar ...
or you could do it more generically to return filtered collections on demand
public ObservableCollection<MonitoredItemViewModel> GetItems(Func<DataValue, bool> matches)
{
//Filter collection with
return ... allItems.Where(x=>matches(x))... ;
}
and call via
GetItems(x=>x.Foo == Bar)
The problem you are going to have is when the items change and should switch from collection to collection. If you were using ReactiveUI this would be incredibly easy as you can use Rx to trigger its built in item tracking and also use its .CreateDerivedCollection(...) to build the new collections automatically (hint, hint :-))
If not then you have a few choices.
You can derive a class from ObservableCollection so that as well as being notified via CollectionChanged when new items are added or removed, or also get notified when the properties of the items change as well.
Or you could make your ItemViewModel immutable so that its properties never change, but instead you drop the old item and add an updated one into the correct collection.
I'm fairly new to WP7 and totally new to Expression Blend.
I have a ListBox bound to a List of custom objects,
List<Person>
Each item in the list contains a custom control, MyControl which is bound to Person.
MyControl contains a TextBox which is bound to the Username property of Person.
All of this works fine. My question is: how do I set a default value for the TextBlock so that it becomes visible in the Designer or ExpressionBlend? With it being data bound, it has no text till it runs ... so I can't actually do any fancy styling using these wonderful tools unless I repeatedly delete the binding code to replace it with a string, make the changes, replace the binding code, repeat. Seems long winded!
Thanks,
Steven
What you want is "Design time data".
There are a number of ways of doing this. Fortunately there are also lots of resources online which explain it.
#Steven Have you looked at creating sample data in Blend to do what you require and then some binding to actually attached the data to the control bound to your list? You might like to check out Blend Sample Data as it guides you through a simple example of doing just that. You might then be able to adapt to to your own ends.
It depends if you are using any MVVM model or not.
My suggestion, if you are not using a MVVM, is to use Blend Sample data, is fast and quick.
If you are MVVM Light I've found very usefull to create two files:
DataService.cs - contains the real connection and data
DesignDataService.cs - contains the sample data
The two libraries are identical, from an call perspective so that in the ViewModelLocator you can swap them:
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
//SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
SimpleIoc.Default.Register<IDataService, DataService>();
}
In the Design class I've decided to create an XML file for each Model so that it's easy to change the sample data and test all possible scenarios.
I then use the Deserialize function to read it:
csNodeList _Copyrights = new csNodeList();
resource = System.Windows.Application.GetResourceStream(new Uri(#"Design/sampledata.xml", UriKind.Relative));
streamReader = new StreamReader(resource.Stream);
serializer = new XmlSerializer(typeof(csNodeList));
_Copyrights = (csNodeList)serializer.Deserialize(streamReader);
Please note that the file sampledata.xml has to be stored in folder Design and must be defined as Content not as Resource.
It is suggested to improve performance and load time.
M
(update) ICustomTypeDescriptor works for my Windows Forms app, but not for Silverlight; Not supported. I will keep investigating this idea though and see where i get to.
(/update)
I have, say a few switch panels (for those that like analogies).
Each of these switch panels has switches that have a Name(string) can be in state(bool) of On or Off.
The switchpanel and switches are objects that have INotify interface on them.
Using the switches Names, I create a list of all possible switch names over the collection and create a dynamic class that has all these Names as properties.
SwitchPanel1 (Switches( Switch1 ("Main",On) , Switch2("Slave",Off)))
SwitchPanel2 (Switches( Switch1 ("Bilge",On) , Switch2("Main",Off)))
Produces a collection of
(Main,Bilge,Slave)
And a dynamic class is produced that has the properties:
SwitchPanel : (SwitchPanel)
Main : (Switch)
Bilge : (Switch)
Slave: (Switch)
The idea is that if the switch panel has a switch with the Name of the property, it is placed on that property. So using a bit of linq
propeties["Main"].SetValue(newSwitchType,SwitchPanel.Switches.FirstOrDefault(sw => sw.Name == "Main"));
I want to cast this new dynamic class to INotfyPropertyChanged AND catch the actual changes on these new properties, so if a switch changes state the dynamic object will report it.
Why? It needs to be displayed in a list view and the list view I'm using has its binding by supplying the Property name, and not the binding path.
It also attempts to catch INotify events by casting the object against INotifyPropertyChanged. This means it will sort and/or group when things change.
If you know of a better way to do this let me know. Please.
You probably don't need a dynamic class. You can implement runtime binding properties via ICustomTypeDescriptor / GetProperties(), creating your own PropertyDescriptor implementation that returns the named switch. It isn't clear what knows first about the change, but you could either use INotifyPropertyChanged, or the older property-specific change event, again tied to each property (so each PropertyDescriptor attaches to, for example, the event in the named switch.
Not trivial, but not impossible either.