I Currently have a XAML ComboBox inside a custom control.
<ComboBox Name="cboPropertyName"
ItemsSource="{Binding}"
Visibility="Hidden"
GotFocus="TxtPropertyName_GotFocus"
DataContextChanged="CboPropertyName_DataContextChanged"
SelectionChanged="CboPropertyName_SelectionChanged"/>
which is connected via Code Behind
DataView DataPropsView = new DataView(_ControlData.Tables["GME_DataProperties"]);
DataPropsView.RowFilter = "Key < 1000";
DataPropsView.Sort = "Key ASC";
cboPropertyName.DataContext = DataPropsView;
cboPropertyName.DisplayMemberPath = "Name";
cboPropertyName.SelectedValuePath = "Key";
cboPropertyName.SelectedValue = Convert.ToInt32(_PropData["SubPropertyValue"]);
But when this customer control has the drop downlist changed the _PropData DataView never changes / Updates.
How can I make this be a TwoWay DataBinding so the DataView updates?
I recommend that you abandon the codebehind and setup all the info in XAML to allow easier setup.
To use two-way binding on needs to bind the target to SelectedValue such as:
SelectedValue="{Binding CategoryID, Mode=TwoWay}"
You seem to have an issue with where the data resides which is really your greatest issue.
Generally one does not bind to a dictionary. Binding is in essence reflection and reflection into a dictionary is problematic to say the least. To do what you need to do, you should create a Notified property on the control and two-way bind to that. On the set for that property, change the dictionary value at the same time.
Also one does not bind to a view to change, because it is a view. Look into using a MVVM pattern, and create the view from the ViewModel, and bind your combobox to the viewmodel's data. Then the two-way binding will work as generally designed.
Related
In Windows Forms I used:
dataGridView.DataSource = new BindingList<MyItem>();
The equivalent in WPF seems to be:
dataGrid.ItemsSource = new BindingList<MyItem>();
What I don't understand (and perhaps I'm doing something wrong) is that in the WPF case, the binding doesn't seem to be bidirectional. That is to say: when I modify a MyItem, it is not automatically reflected in the view.
Use ObservableCollection<MyItem>.
MyItem must implement INotifyPropertyChanged and raise PropertyChanged when any of its property values changes.
That'll update the grid cells.
If you plan to do anything much with WPF, learn MVVM and use Binding. Assigning a collection to a property doesn't bind it.
XAML:
<DataGrid
x:Name="dataGrid"
ItemsSource="{Binding MyItemCollection}"
...
/>
You can also create a Binding programmatically, if you really want to make a lot of extra work for yourself.
Seems like ObservableCollection has some improvements over BindingList.
I'm very new to WPF. I'm trying to bind to a property a row in a DataGrid so that when the row's clicked the property is set. The ItemsSource that's bound to the DataGrid is an ObservableCollection of objects of type Field.
I've tried to bind to the SelectedItem attribute on the DataGrid, but the property is not being called. I'm using almost identical code to bind to the SelectedItem of a ComboBox and this is working fine. Is there a difference that I don't know about?
<ComboBox ItemsSource="{Binding RecordTypes}" SelectedItem="{Binding SelectedRecordType}" ...
<DataGrid ItemsSource="{Binding Fields}" SelectedItem="{Binding SelectedField}" ...
In my ViewModel:
private Field SelectedField
{
get
{
return _selectedField;
}
set
{
_selectedField = value;
}
}
(I will use auto properties later, it's just currently set up like this so that I could break when the property was set).
I'm not sure if it makes a difference, but the DataGrid is composed of 2 DataGridTextColumns and a DataGridTemplateColumn, which contains a checkbox.
Does anyone have any ideas? I'd really appreciate any suggestions.
To confirm, the reason that I want to listen to the click of a row is so that I can have the checkbox be checked whenever a row is clicked. If there's a better solution for this then please let me know.
You need to make it a two-way binding:
SelectedItem="{Binding SelectedField,Mode=TwoWay}"
That propagates changes in the view (user selects an item, SelectedItem changes) back to the viewmodel ("SelectedField" property).
Also, as #KevinDiTraglia pointed out, you need to make sure that the viewmodel property SelectedField is public, not private, otherwise the binding will not be able to access the getter/setter.
I'm using DataGrid bound to List property in my user control:
<DataGrid x:Name="dataGrid" ....
ItemsSource="{Binding ItemSorce, ElementName=UserControl}"
....>
My problem is that I need it updated every time I change the source.
I had the user control implement INotifyPropertyChanged and do raise PropertyChanged event, but the DataGrid original content remains the same.
I've read that for the DataGrid to change, I should set BindingSource between ItemSorce and the binding, but all examples I've seen are doing this via c# source code.
How do I set BindingSource via xaml, and is this the best way to synchronize the DataGrid and ItemSorce?
Use a ObservableCollection<> instead of a List<> as it is designed for bindings.
My Sql stored procedure returns a datatable "dt".how would i use Selected columns from that datatable and bind them to specified values in my datagrid.
i am currently using this
DataView view = new DataView(dt);
DataTable cat = view.ToTable(true,"categoryID", "category");
how would i bind the category ID and category columsn in my datagrid
here is my datagrid column
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding}" Header=" " />
<DataGridTextColumn Header="Category" />
</DataGrid.Columns>
You should use a MVVM approach here.
The DataTable should be managed by the ViewModel and the the columns that you want to display use can be made available to your view by properties of the ViewModel.
[EDIT]
The amount of work you would need to invest is dependent on what you want to achieve. If you only want to display the values it might be sufficient if you convert the DataTable into a ObservableCollection and then bind ObservableCollection to the UI element.
Or, you can bind the DataTable directly to your DataGrid and set the AutoGenerateColumns="True" property.
You can find an example here: Bind Datatable with DataGrid in WPF & MVVM
[EDIT 2]
In short, a ViewModel is the class that should be visible to your WPF window. It contains some public properties that signal the View when the underlying data has changed by implementing the INotifyPropertyChanged interface.
The advantage of this approach is that the View gets decoupled from the business logic that works with the actual data. It does not need to be refreshed manually but is automatically informed by the ViewModel. WPF was strongly designed to make use of the MVVM pattern, so if you dig into it, you will find it very rewarding to work with.
It makes working with WPF very easy and helps structuring class responsibilities.
A nice tutorial on how to get into using the MVVM (Model-View-ViewModel) approach and how to use ViewModels can be found in this MSDN article: WPF Apps With The Model-View-ViewModel Design Pattern. That one helped me a great deal to understand MVVM.
I am databinding a textbox of a UserControl to a property as follows.
<TextBox Name="txtData" Text="{Binding MyData, Mode=TwoWay}"/>
But when I click the Submit button on the page that hosts the usercontrol after entering some text in the txtData textbox of the usercontrol, userControl.MyData returns null. What can I do to have the txtData.text value be assigned to property other than through TextChangedevent?
From your comments you wish to update userControl.MyData when the TextBox.Text changes.
From the binding perspective TextBox.Text is the target and MyData is the source so strictly speaking this is a OnWayToSource binding (to source => to MyData) - so there should be no need to implement INotifyPropertyChanged. But that is not the issue.
The way the binding is currently written, the MyData property expects to be found on the DataContext of the TextBox - is that the case? You could fix the data context or possibly use some other binding source e.g. ElementName or RelativeSource - difficult to say without seeing more xaml.
You might also consider setting UpdateSourceTrigger=PropertyChanged on the binding.