Changing Combobox should update entity EF6 - c#

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.

Related

Combo Box Two Way Binding resets Properties

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.

how to bind dataSource to combobox?

I am trying to bind data with combobox but couldn't bind it.
CBFolders.ItemsSource = client.GetNewsLetterFoldersAsync("token", 12, 3427).AsDataView();
In this code I am using web service which method GetNewsLetterFolders return data table.
Please help me how I can bind this??
Return type of web service method should be a model class. If it's returning folderId & Description and both properties should member of FolderData class. Hence FolderData essentialy become table.
I consider service method GetNewsLetterFoldersAsync returns List. So combox box should be bind like this
CBFolders.ItemsSource = await client.GetNewsLetterFoldersAsync("token", 12, 3427);
<ComboBox x:Name="CBFolders" SelectedValuePath="folderId" DisplayMemberPath="Description" />
SelectedValuePath should be bind with that property which is needed while selection changes in ComboBox. DisplayMemberPath should be bind with that property which is needed to show in ComboBox.
CBFolders.SelectedItem will return selected folderId
You need to convert the datatable to List when you are binding it to ItemsSOurce property. CBFolders.ItemsSource = client.GetNewsLetterFoldersAsync("token", 12, 3427).GetList(). Hope this helps.

Finding items in listview by typing first letter WPF

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

DataGrid - grid selection is reset when new Data is arrived

I have such DataGrid
<DataGrid AutoGenerateColumns="True" HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" ItemsSource="{Binding DataList}" IsReadOnly="True"/>
In my ViewModel I have such field:
public ObservableCollection<ConsoleData> DataList { get; set; }
And such method which is called every second:
private void model_DataArrived(List<ConsoleData> dataList)
{
DataList.Clear();
dataList.ForEach(x => DataList.Add(x));
}
Grid displays some real-time data and updates every second.
The problem is - when I select some row in the grid, the selection is reset after a second (when new data is arrived).
I guess probably this is because I Clear DataList every time?
How to solve this problem?
Before clear, pick up the currently selected item (a unique identifier if you have one) then attempt to highlight it again on update and if it's not there anymore just don't highlight annything.
The way I've set up a updating lists in the past is:
Create an Update method in you object (ConsoleData) that you can pass a copy of that object and the object updates itself. The object also needs to implement INotifyPropertyChanged.
In you model_DataArrived method in the ViewModel find all matching objects and use the Update method from step 1 to update the objects.
Find all new objects and add them to you list (DataList).
Find all missing objects and remove them from you list (DataList).
In case the new dataSource still contains your last selected item and if you are following MVVM pattern. All you need to do is Raise PropertyChanged event for your selecetdItem once data source is reloaded. Make sure your viemModel implements INotifyPropertyChanged interface.
EDIT
And in case you don't want to clear your datasource every now and then. Simply, use the ObservableCollection in place of the generic list. It internally implements INotifyCollectionChanged, so any addition or deletion of item in your collection will be reflected on your UI.

Set WPF Datagrid column as a Combobox itemsource

I have a Combobox, in which I would like its items to be the column data that is located on a DataGrid. Is there anyway to set the Combobox itemsource to be a specific column of a DataGrid?
Right now I'm iterating each row of the DataGrid, getting the field's data and adding them to the Combobox, but that means that I would have to clear all the items and reiterate everytime the DataGrid is modified.
You can set ItemsSource and DisplayMemberPath properties:
comboBox1.ItemsSource = dataGrid1.ItemsSource;
comboBox1.DisplayMemberPath = "ColumnName";
I Think you'are taking the wrong approach. Your data grid must be bound to a collection of object. I guess you could just build another collection by extracting the desired fields (for example with linQ) and expose this new collection to your view such that you can bind your combobox.
I you want to keep this second collection updated, make your first main collection an ObservableCollection such taht your can subscribe to CollectionChanged Event. In the event handler, just manage the add and remove in your combobox source collection.

Categories

Resources