i have entity FDataTableColumn which has field referenceFieldId which is long type and refs onto id of such column. On the create page i have combobox with list of all columns, i want to chose one and to put its id value to my referenceFieldId.
this is my combobox:
<combobox model="#load(fdtcm.fDataTableColumns)" selectedItem="#bind(fdtcm.fDataTableColumn.referenceFieldId)" width="50%">
<template name="model">
<comboitem label="#load(each.table.tableName.concat('.').concat(each.tableField))" value="#bind(each.id)"/>
</template>
</combobox>
Looks like it's all good but i got this exception
Cannot convert FDataTableColumn{id=6, type=STRING, tableField='EMAIL'} of type class ru.webvane.framework.metadata.entity.FDataTableColumn to class java.lang.Long at [file:/E:/apache-tomcat-7.0.28%20(64)/webapps/fw/fw/importData/dataTableColumn/input.zul, line:86]
i understand that my combo is trying to save the whole object to referenceFieldId, but why ? because i'm trying to save object's id
value="#bind(each.id)"
can anyone help me or explain what i'm doing wrong. thank you
SergeBud,
It is possible to do so but as askkuber already points out, the class of what's inside the combobox is the class what will be saved.
Now you just have to implement your own custom converter :
then it should the zul be like :
selectedItem="#bind(fdtcm.fDataTableColumn.referenceFieldId) #converter(fdtcm.myConverter)"
You can check following code which written by me zkframeworkhint.blogspot.in/2013/05/zk-combobox-with-selectoption.html this will explain you the right way to use Combobox.
EDIT :-
Then you can check this link Combobox this will help you
Look selectedItem should be object of the class FDataTableColumn but in you case you refer it as id which is Long it could be a reason of the exception make changes in your code.
Related
I have a question about “Master\Detail” data binding using MVVM and I hope you can help me with it:
Let say my Master ModelView is “ProductModelView” (for Product Entity) and the Product Entity has a property named ProductInventories of type Entity Collection. I defined a “DomainCollectionView” in my master ProductModelView with name: “ProductViewDCV”
I do following items to fill my master and details Datagrids:
1-Set the DataContext of my page to my ModelView : ProductModelView
2-Bind master Datagrid (name: masterDG) to ProductViewDCV.
3-Bind detail Datagrid (name: detailDG) to ProductInventories property of my master ProductViewDCV :
<sdk:DataGrid x:Name=" detailDG "
ItemsSource="{Binding Path= ProductViewDCV. ProductInventories }"/>
The Program works well ,As I change the row in master DataGrid , The current item in the child DataGrid also changes.
But my question and Problem :
When I bind my detail (child) DataGrid as mentioned in step 3 , the child DataGrid is bound to “EntityCollection” not a View Object Like “PagedCollectionView” or “DomainCollectionView” ,So I can’t use benefits like Sorting ,Grouping and Paging on my child (detail) DataGrid. I want to know :How I can bind my child DataGrid to a View Object in MVVM pattern to use Paging option.(Namely I want to have Paging and Grouping Options in my child DataGrid.)
Look forward to receiving your reply.
Hello.
I really appreciate your kind and quick answer. I did as you said ,but I encounter a problem and I hope you help me:
Method:
In my “ProductModelView” (for Product Entity) I defined following objects:
1-private DomainCollectionView _ProductViewDCV; (As Master(Parent) View)
2-private PagedCollectionView _ProductViewPCV; (As Detail(Child) View)
3-In Constructor of “ProductModelView” class, I assigned an EVentHandler to “_ ProductViewDCV”(my DomainCollectionView as Master view):
this._ProductViewDCV.CurrentChanged+=_ProductViewDCV_CurrentChanged;
this._ProductViewDCV.Refresh();
4-In the EventHandler , I Create a new “PagedCollectionView” (my Detail/Child view) and assign it to my _ProductViewDCV :
if (_ProductViewDCV.CurrentItem != null)
{
_ProductViewPCV = new PagedCollectionView((_ProductViewDCV.CurrentItem as BA1.Web.Product).ProductInventories);
//ProductViewPCV.Refersh();
}
5-In my View File (XAML file), I have two Datagrids which are configured as follow :
Page DataContext is set to an object of my ModelView : ProductViewModel
sdk:DataGrid x:Name="dgParent" Grid.Row="1" ItemsSource="{Binding Path=ProductViewDCV}"//my Master/Parent DataGrid
sdk:DataGrid Grid.Row="2" x:Name="dgDetails" ItemsSource="{Binding Path=ProductViewPCV}//My Detail/Child DataGrid
Problem :
When I change the current row in my Master/Parent DataGrid , nothing happens in Detail/Child DataGrid and testing the Detail/Child DataGrid’s Itemssource property , returns “Null” ,not an object of “PagedCollectionview”.
Where’s my problem and why doesn’t the Detail/Child DataGrid get updated in response to Master/Parent current item changing? (Testing shows that ProductViewPCV itself changes when it’s parent collection changes.)
Again let me thank you for giving me advices on this problem.
Off the top of my head, there's a few problems I can see. You should instantiate the _ProductViewPCV PagedCollectionView property in the constructor, and not create new instances of it in the _ProductViewDCV_CurrentChanged event handler. If you did want to do this, then you need to notify the view that the value of this _ProductViewPCV property has changed by raising a PropertyChanged event. However, you shouldn't do this as it's likely to result in a memory leak.
You'd be best off wrapping an observable collection in the PagedCollectionView, and simply updating the contents of the observable collection in the _ProductViewDCV_CurrentChanged event handler I think. The view should update automatically I think. Sorry, I'm a little rusty on this, but I think that should work for you.
I am fairly new to mvvm and WPF so I am looking for some pointers to achieve the following.
I would like to create a search section in my app that builds up the search options based on whatever the users selects as their criteria.
So for example the first combo box of the search offers the top level of choices:
Date of Message
Gateway
Direction
Etc..
......
The second section is my operator
So, for example if Date of Message is selected then the user is offered another combo box of choices
Is Between
Last Week
Last Month
Etc..
The last section of the search is based on the operator above, so if Is Between is selected the form displays two Date Pickers from and to. If on the other hand Last Week is selected then nothing is displayed as the search can directly call my SetActionLogsForLastWeek() method once I click my search button.
If the user selects Gateway from the initial list then another combo box is build with a list of choices based on gateways.
I am looking for a tutorial or previous post that points me in the right direction on achieving my goal of building WPF elements based on selection choices from other elements.
Thanks
This is a rather extensive question, and as such there is no definitive answer. I will describe how I would handle this problem. Keep in mind that this might not be the best solution out there.
In order to render the controls which depend on the first combo box use data templates and distinct view models. In the resource section of your main view, or an external resource if you have defined one, write something like this:
<DataTemplate DataType="{x:Type vm:YourViewModel}"> <vw:YourView /> </DataTemplate>
You will have to import the namespaces containing your viewmodels and views (vm: and vw: here). Using content-controls you can render views depending on their viewmodels:
<ContentControl Content="{Binding CurrentViewModel}"></ContentControl>
In your code behind, you will have to have a ViewModel which you can bind to. Depending on the selection of the first combo box, you can now swap out the ViewModel in the code behind in order to render the dependent combo boxes - or nothing at all!
In order to illustrate, let me provide some sample code. Lets start with you main view model. Thats the one containing the collection the first combo box binds to (e.g. the strings "Date of Message","Gateway"...)
public class MainViewModel : BaseViewModel {
public IObservableCollection comboBoxItems;
public BaseViewModel ControlViewModel {get; set;}
private String selectedItem;
public String SelectedItem {
get {
return selectedItem;
}
set {
selectedItem = value;
OnPropertyChanged("SelectedItem");
ChangeControls();
}
}
private void ChangeControls(){
switch(selectedItem):
//swap out the control view model here e.g.
controlViewModel = new GateWayControlViewModel();
}
}
Btw, BaseViewModel is an abstract class which all view models inherit from. It implements INotifyPropertyChanged.
In your main view it is enough to have content control binding to the control view model, as well as the first combo box:
In your resources.xaml you define the data template, as discussed before.
<DataTemplate DataType="{x:Type vw:GatewayControlViewModel}"> <vw:GatewayView /> </DataTemplate>
This will render the GateWayView if the ViewModel, which the ContentControl in the main view is bound to is equal to GateWayControlViewModel. Finally, your GatewayView could look like this:
<ComboBox ItemsSource="{Binding Gateways}"
SelectedValue="{Binding SelectedGateway}" />
Obviously, you will have to make sure your GatewayControlViewModel actually contains the items and properties mentioned in the view. It will also need to derive from BaseViewModel.
I hope this gives you some ideas. Additionally, you might find this link useful (as it contains some very useful tips on how to approach MVVM).
If you want to implement Search in Collections for example in as in Combobox or Grid you should read a bit about ICollectionView. The ICollectionView will allow you to filter collection based on your search criteria. In your example you can also do this by handling selection changed events at the viewmodel and create method to update your data based on selected inputs.
I'm trying to figure out how to display the data from a dictionary property of a list inside a WPF DataGrid GridViewColumn
All the examples I find only appear to map to list of simple entities that can be . traversed like {Binding Answers.Title}. Mine however would be more like {Binding Answers["Title"]} which doesn't work in XAML
I'm missing something obvious here. Any ideas?
Edit: The list contains an entity that contains a Dictionary. Where Answers is the dictionary in the entity.
If I understand you correctly, you have a dictionary as the DataContext, and you need to display either its key or value as ListBoxItem. You can try following :
Here Data is the dictionary you can change the DisplayMemberPath="Key", if you need to display key. This can also be used to display data from a property while a complex object is in DataContext.
I'd imagine you simply bind the item source to the dictionary.Values as you would any collection and then create a data template as usual for the item
I.e. mygridview.datacontext = mydictionary.values
I have a simple scenario and a issue with it which I just cant seem to resolve past few days.
OK, first of all I use MVVM to bind my View on a ViewModel. I have in my view several text boxes which binds to several properties (most strings) in ViewModel (binds actually to an Custom Object (type Person, name SelectedPerson) with strings properties , object which is a property of the viewmodel). This object implements INotifyPropertyChanged and IDataErrorInfo. It has also an int property named Age. I also have in my view a button which is bound to a command in my viewmodel, a command which inside CanExecute test the SelectedPerson's properties and return true if all are correct.
Now my issue is: if I put in my Age text box from my View something not int, a red tectagle will appear (is normal, because there is an exception to the conversion), but in that specific moment, to the object behind (SelectedPerson, type Person) there isn't sent the newValue (the setter to that property Age, or the IDataErrorInfo Members don't intercept the value .... I guess it is normal because there isn't any "new" value, because I put an incorrect format in the text box in the first place).
So, maybe I repeat myself, the issue is: if the new Age (new incorrect Age) isn't set, then the Object behind still hold last value, which if it was correct then the command itself it's correct (the can execute will return true) and the button is enabled
As you can imagine I want the submit button (it's a button which saves current person details in data storage module) to be disabled when current properties don't pass through conversions methods.
PS: I used a IValueConverter class , and on that text box binded to Age, I made use of my StringToIntConverter class....but on Convert Method I don't know how to pass the SelectedPerson binded object (I just pass the text value, and return the int value)
I guess one way to do it could be by using MultiBinding scenario , but I'm not sure.
If I could pass the SelectedPerson inside Convert method from that converter I could invalidate that command from the converter itself.
Sorry for my English, I know it's far from perfect :) and thanks in advance for your time.
I think the cleanest solution would be to bind the textbox to a string property instead, and update your view model so that your IDataErrorInfo implementation for that property name attempts a string to int conversion and returns the result of that. Your CanExecute test would also then include this conversion as part of the validation test.
I'm trying to improve on a Winforms project where datatable rows are stored in the Tag property of ListViewItems. When the datatable is refactored to List<T> (or actually classes containing lists) it would help immensely if I could make the Tag property generic by using a subclass of ListView.
In the best of worlds, I'd want the Tag property to be replaced by a public T Tag{get; set;} that wraps base.Tag and casts it.
Second best would be Obsoleting Tag and providing a new property like TypedTag working like above.
I think this would involve subclassing or composite aggregation of at least ListView, ListViewItemCollection, SelectedListViewItemCollection and ListViewItem, and I'm not sure how to do it.
In short:
ListView<Employee> lvwEmployees;
should result in this being possible:
Employee selected = lvwEmployees.SelectedItems[0].TypedTag;
And give a compilation error for this:
DataRow selected = lvwEmployees.SelectedItems[0].TypedTag;
Is it possible? Is it already done?
Project is dotnet 2.0 but I think I'll try to have it upgraded if it helps this matter.
EDIT: It turns out that the owner constructor argument is all a certain collection needs to hook up to the inner collection. Hence the following works:
ListView a = new ListView();
a.Items.Add("Hello");
Assert.AreEqual(1, new ListView.ListViewItemCollection(a).Count);
This makes it rather easy to create a generic tagged ListView. I'll post a complete solution later. :)
EDIT2: Here's the solution:
http://thecarlr.blogspot.com/2010/11/generic-listview.html
EDIT3: For designer support, just add a non generic subclass and use that.
Example: If you intended to use ListView<Employee> in the form, create a ListViewEmployee : ListView<Employee> in another file, and use ListViewEmployee in the form.
The easiest way to add one of theese listviews would be to add a normal listview to the form, and then change it's type in the source files. (And if you don't know where it's declared or instantiated, find out or use the normal listview instead.)
You made the wrong class generic. SelectedItems[0] is a ListViewItem, not a ListView.
There isn't anything you can do to change the type of the Items and SelectedItems properties. You can certainly derive your own class from ListViewItem and just add the property you want to store. No need for another Tag property. You'll have no trouble adding them but you'll need to cast back to your derived class when you retrieve them back from the Selected/Items collection.
In general, avoid this kind of code by using the ListView only as a view of your model. The ListViewItem.Index should then always be good to get a typesafe reference back from your model.
Here's the solution:
http://thecarlr.blogspot.com/2010/11/generic-listview.html
Enjoy :)
/Carl
VS Designer simply cannot handle abstract or generic controls (not for want of asking).
One way around that limitation is to write a type safe wrapper around a standard ListView.
Something like this:
public class TypedListView<T> where T : class
{
public TypedObjectListView(ListView lv) {
this.lv = lv;
}
private ListView lv;
public virtual T SelectedObject {
get { return (T)this.lv.SelectedItems[0].Tag; }
}
// Lots more methods/properties
}
You create a normal ListView in Designer, and then when you wanted to access it, you create and use your adapter instead. Like this:
var typedListView = new TypedListView<Employee>(this.listView1);
Employee selectedEmployee = typedListView.SelectedObject;
You would need to provide a typed version of every ListView properties or method you wanted to use.
The ObjectListView project takes this approach to create a TypedObjectListView which does exactly what are you asking for.