I have a combo box in a datagrid located in an activity. Based on combobox selection I populate another grid with controls programatically. User enters some data in these controls and then saves it. The object that the combo box is bound has many properties of which two are used in selected value path and display member path. The data is bound using two way binding for combo box. When the saved activity that has been placed on a workflow is reopened the data is reloaded correctly and the correct object is value is set in the combo box. But on UI rendering only the values that are attached with the combo box remain intact (i.e those in selected value path and display member path) the rest are reset.
Any idea why this might be happening?
P.S: Setting the binding to OneTime solves the problem of retrieval but any changes that are made on the UI after loading are not reflected back.
Code-Behind:
public ObservableCollection<MyRule> AllRules {get;set;}
public MyRule myRule{get;set;}
In datagrid Loaded Event I populate the AllRules as:
AllBusinessRules.Add(new MyRule () { RuleId = item.Id, RuleName = item.Name});
where item.Id and item.Name are obtained from the database via service call.
In the same event if I also load any previously saved rules as:
myRule=SelectedRule;
where SelectedRule has RuleId, RuleName, Inputs and Outputs as well.
Code:
<ComboBox
ItemsSource="{Binding Path=AllRules}"
SelectedItem="{Binding Path=myRule,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
SelectedValuePath="RuleId"
DisplayMemberPath="RuleName">
<DataTemplate>
<TextBox Text="{Binding Path=myRule.RuleName}"/>
</DataTemplate>
</ComboBox>
Class:
public class MyRule{
public int RuleId{get;set;}
public string RuleName{get;set;}
public List<string> Inputs{get;set;} //properties that are reset when the UI renders
public List<string> Outputs{get;set;} //properties that are reset when the UI renders
}
The Inputs and Outputs properties are obtained from the programatically generated controls via reflection and added to the object populated by combobox and saved.
I have studied about this problem here but the solution does not solve my problem. Any help would be great.
SelectedValuePath, DisplayMemberPath are set wrongly. DisplayMemberPath should be "RuleName". SelectedValue, SelectedValuePath are not needed as you have set SelectedItem. SelectedItem will get the chosen item automatically because of Binding. From the myRule object you can access other properties.
It took a lot of time to investigate what was wrong but now that I know its just quite simple.
As I have shown that in the datagrid's Loaded event I used to set the ItemsSource of the combo box and in the item source I have only set the properties RuleId and RuleName.
Problem:
So the problem was that when I assigned the value i.e the selected value on reloading the combobox e.g. myRule=SelectedRule the other properties i.e. Inputs and Outputs are not there in the ItemsSource. That is why the selected object though correct did not have Inputs and Outputs as the SelectedItem was from ItemsSource of the Combo Box giving me the impression that the two way binding had somehow reset the values of properties not bound with the combo box.
Solution:
In the end I wrapped my MyRule Object in another object like RuleInformation i.e
public class RuleInformation{
public List<string> Inputs;
public List<string> Outputs;
public MyRule myRule{get;set;}
}
where MyRule is like:
public class MyRule{
public int RuleId{get;set;}
public string RuleName{get;set;}
}
So the combo box is bound to the MyRule object whereas the inputs and output properties remain untouched in the upper object.
Related
So I have a listbox and a class. This class is called 'Mission' and has three properties: Name, IsStarted and IsCompleted.
I have used a BindingList and set the datasource of the Listbox to that BindingList. This works fine, no problems so far.
What I don't know how to do (and I hope it's possible) is to bind the properties IsStarted and IsCompleted to two CheckBoxes, so that if I change which Mission is selected, those CheckBoxes will change to reflect the properties of the SelectedItem.
I appreciate I can do this by using the event of SelectedItemChanged on the ListBox, but I would like to have a two way binding so that if I were to check or uncheck the CheckBoxes, the data in the class would change.
You don't need to use events, it's enough to use data binding:
missionsListBox.DataSource = bindingList;
missionsListBox.DisplayMember = "Name";
isStartedCheckBox.DataBindings.Add("Checked", bindingList, "IsStarted");
isCompletedCheckBox.DataBindings.Add("Checked", bindingList, "IsCompleted")
This way, the ListBox will act as an index for mission objects and it shows a list of missions. When you select an item, it shows values of IsStarted and IsCompleted in corresponding check box controls and you can change those values for selected item using check boxes.
I have a normal data binding situation where my underlying question object properties are bound to columns in a devexpress XtraGrid.GridControl. However, I have one text property that takes the form of "{Question|True},{Question|False}". These must be mapped to checkboxes in the grid (potentially many per property). Is it possible to use data binding to bind this string property directly to a cell, providing checkbox editing, perhaps using a CheckedComboBox? I'm thinking I'd need an intermediate step in the binding process to map the original string to checkboxes, and then from the checkboxes back to the string.
Otherwise my current thinking is to create another layer of objects, which contains a new object for each of the checkbox options, but if I could somehow interrupt the default binding process with a mapping from the above text to the checkboxes in a CheckComboBox I'd be able to bind straight to the underlying objects.
If I understood you well I think that you should change your question object
to contain bool property. Bool properties are bound to grid as checkboxes, so it will work automatically.
I know that your real value of that property should be string "{Question|True}"
so you can set that property in that way:
private string question;
private bool questionBool;
public bool QuestionBool{
get{return questionBool;}
set{
if(value)
question = "{Question|True}"};
else
question = "{Question|False}";
questionBool = value;
}
I ended up converting the text into a collection of CheckboxQuestionAndAnswer objects which I then bound to the grid, then converting them back into a single text string for writing the data back.
So basically, I have an entity, I've used a LINQ query to get some items and bound that to a combobox.
What I'm trying to do is have the entity update when the item in the combobox is changed without doing a manual update in the Combobox.SelectedIndex/SelectedValue changed event. I'm just wondering if there is a better way?
Pseudo code:
SomeEntity se = new SomeEntity();
var q = from x in se select x;
cbComboBox.Datasource = q.ToList();
cbComboBox.DisplayMember = "SomeValue";
cbComboBox.ValueMember = "SomeValueID";
cbComboBox.SelectedValue = se.SomeValueID;
So the combobox shows the correct value I want. That's fine.
Here's the thing, when the user changes the combobox, I want se.SomeValueID to reflect that change.
I know I can set se.SomeValueID in the combobox SelectedValue event, but is there a better way? Where se.SomeValueID automagically gets updated?
Assuming your question is about Windows Forms. To bind SelectedValue to an object's property you can add custom binding:
cbComboBox.DataBindings.Add("SelectedValue", se, "SomeValueID");
That binding is two-way and there's no need in cbComboBox.SelectedValue = se.SomeValueID; line.
You should achieve this using Bindings defined in XAML instead of C# code behind code, here is an example:
<ComboBox ItemsSource="{Binding SomeList}"
DisplayMemberPath="SomeField"
SelectedItem="{Binding CurrentItem, Mode=TwoWay}"/>
In this way you can have in your viewmodel class the list of entities (SomeList) and an object of the same type (CurrentItem) that will be updated every time the user change the selected item in the combobox. If you don't need the entire object, you can bind the selected value to a property exposed on your viewmodel with the same time of the id.
Hope this helps.
I have a listview which binds customer informations from database. There are 15 columns which are binded in that listview. One of that column is Customer Name.
I want to be focused them when I type their name's initial character from the keyboard. Have you any idea to make this ?
This is my listview's XAML code
<ListView x:Name="datalist" ButtonBase.Click="datalist_Click" ContextMenuOpening="datalist_ContextMenuOpening" MouseDoubleClick="datalist_MouseDoubleClick" SelectionChanged="datalist_SelectionChanged"
MouseUp="datalist_MouseUp" PreviewMouseUp="datalist_PreviewMouseUp" >
Try to operate only on Model/ModelView and not on UI directly (as much as it possible).
For example, define in ModelView a property
public bool Focused{
get ..
set... //OnPropertyChanged
}
nd bind it to the UI elements corresponding property.
After this the only thing you need to do is t simply
find an element in binded data (ModelView objects)
set it's Focused property to true
I have a combo box that is bound to a collection that is essentially a list of Name/Value pairs. The collection can have multiple items with different names, but the values may be the same.
public class NameValuePair
{
public string Name { get; set; }
public string Value { get; set; }
}
public class NameValuePairCollection : List<NameValuePair>
{
public NameValuePairCollection(): base() { }
}
So inside my User Control I have a private field called items which is an instance of that NameValuePair collection:
private NameValuePairCollection items = new NameValuePairCollection()
Somewhere along the lines that collection gets initialized and items get added to it. However, the problem I see is when I try to set the selected index of the combo box that is bound to this collection:
this.CboItemsSelector.SelectedIndex = 3;
or
this.CboItemsSelector.SelectedItem = this.items[3];
The selected item is there but the UI is not synchronized. The UI's selector still defaults to the first item in the list, even thought the SelectedItem's Name and Value properties DO IN FACT CORRESPOND to whatever is in index 3 of the underlying collection!
Any ideas on how to force the ComboBox to refresh itself? Or just plain fix the issue? I know it's quite small issue, but it is big enough to force me to rewrite quite a bit of code.... :( :( :(
Thanks!
You need to inherit from ObservableCollection, not List. Otherwise no OnPropertyChanged events will be fired and the bound control wont know the data has been updated.
Do the selected Item's Name and Value properties match or is the SelectedItem an instance from within the same collection? .Net will not know to compare the items by name and value unless you tell it to, else it will use object equality to try and find the item in your list. If you are setting the selected item to an instance that is not actually in the list (but has the same properties) .net will not find it in the list. You have 2 options, override equality for your object and force comparison of properties, or ensure that you always set the selected item to an item in the list. Also try what Andy May suggested and do 2 way binding on the ItemsSource and on the SelectedItem, should work then