How do I bind child entity detail fields to text boxes? - wpf

My RadGridView is bound to child records via the parent entity's navigation property. Users can edit records in the grid. Now I'd like to also allow editing of child records outside of the grid. After selecting a record in the grid you could edit it using text boxes. I can't seem to find the right binding statement for each text box. My working child grid XAML looks something like this:
<telerik:RadGridView Name="childGrid" ItemsSource="{Binding ChildEntitiesNav, Mode=TwoWay}" IsSynchronizedWithCurrentItem="True" AutoGenerateColumns="False">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn DataMemberBinding="{Binding ChildFieldOne}" Header="Child Field One"/>
<telerik:GridViewDataColumn DataMemberBinding="{Binding ChildFieldTwo}" Header="Child Field Two" />
I've added text boxes corresponding to each grid column but I can't get any data to appear. I've tried these text box binding statements:
Text="{Binding Path=ChildEntitiesNav.ChildFieldOne}
and Text="{Binding Path=ChildFieldOne}
I'm using WPF and Entity Framework database first. What is the correct binding statement for editing child detail entities via a parent navigation property?
Thanks in advance.
ANSWER: Andrey's response led me to the solution. I simply needed to bind my text boxes to the grid's SelectedItem (rather than binding to the child entity). I added the grid name as the DataContext to my text box:
<TextBox Name="ChildFieldTextBox" Text="{Binding Path=ChildFieldName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" DataContext="{Binding ElementName=childGrid, Path=SelectedItem, Mode=TwoWay}" />
These links helped:
Here and here.

Here is an article which may help you. It describes how to bind a control to a property of DataGrid's selected item.
Or you can to add SelectedChildEntityNav property to your ViewModel. The RadGridView declaration will look like this:
<telerik:RadGridView Name="childGrid" IsSynchronizedWithCurrentItem="True" AutoGenerateColumns="False"
ItemsSource="{Binding ChildEntitiesNav, Mode=TwoWay}"
SelectedItem="{Binding SelectedChildEntityNav, Mode=TwoWay}">
After that you're able to bind the textboxes to SelectedChildEntityNav's properties.

Related

How do I bind the visibility of a CheckBox in a DataGrid to the DataContext of that row?

I have a JibGrid DataGrid like so (JibGrid is an open-source relatively simple subclass of a standard DataGrid to implement stuff like filtering etc):
<dataGrid:JibGrid ItemsSource="{Binding AvailableRDs}"
FilteredItemsSource="{Binding AvailableRDs}"
SelectedItem="{Binding SelectedAvailRD}"
AutoGenerateColumns="False" >
<dataGrid:JibGrid.Columns>
<DataGridCheckBoxColumn Header="Add?" Binding="{Binding Add}" Visibility="{Binding GetAddVisibility}"/>
<DataGridTextColumn Header="Tag" Binding="{Binding Tag}" />
<DataGridTextColumn Header="Revision Tag" Binding="{Binding RevisionTag}" />
<DataGridTextColumn Header="Current System" Binding="{Binding SystemStr}" />
</dataGrid:JibGrid.Columns>
</dataGrid:JibGrid>
The intent is that there is a custom class for each row that provides properties for the content of each cell in that row - Tag, RevisionTag, etc. All of that works fine. What I can't get to work is that Visibility binding. I would like for the checkbox in each row to be invisible if the CanAdd property on the class representing that Row in the DataContext returns False. When I add the Visibility binding in XAML as above, it seems that what happens is that WPF attempts to apply this binding to the actual column instead of for each row, so the binding fails to connect. I can go in using WPF explorer and manually bind a row's checkbox visibility DependencyProperty to the CanAdd property of the Row's datacontext, and that works fine, but I can't figure out how to, in XAML or code, cause it to generate that binding for the checkbox in every row automatically. Anybody have any ideas on that?
I have searched around for questions like this, and it seems that, for some reason, everybody wants to change the visibility of the column itself based on something in the datacontext of the whole grid, and nobody else wants to change the visibility of things in individual rows based on that row's datacontext. I tried the solution here while I was trying to figure this out, and that's what that answer is trying to do.
You can use DataGridTemplateColumn and BooleanToVisibilityConverter to achieve the desired result
Add BooleanToVisibilityConverter to your resources
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
Set Converter for the DataGridTemplateColumn binding
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Add}"
Visibility="{Binding CanAdd, Converter={StaticResource BoolToVis}}" ></CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

RadGridView Selected Row

I have a Telerik GridView. My GridView has several columns in it. The first column is a checkbox, and when I check or uncheck it, it changes a property in my Model named IsSelected!
The part of my code looks like this one:
<telerik:RadGridView>
<telerik:RadGridView.Columns>
<telerik:GridViewColumn Header=""
IsFilterable="False"
IsSortable="False"
IsReadOnly="True"
HeaderCellStyle="{StaticResource GridViewDefaultCheckboxStyles}">
<telerik:GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}"
Style="{StaticResource GridCheckBoxStyle}">
</CheckBox>
</DataTemplate>
</telerik:GridViewColumn.CellTemplate>
</telerik:GridViewColumn>
<!--Other columns-->
</telerik:RadGridView.Columns>
</telerik:RadGridView>
Now I want to remove the checkbox, and when I click a row in my grid(anywhere in the row), I want the IsSelected property to change its value. How can I achieve that?
I mean when I click a row, the selected row should be bound somehow to my IsSelected property, without braking the MVVM pattern.
Consider adding a custom behavior to the GridView that listens to the selection changed event, and updates the IsSelected item. This should keep your design clean.

WPF Databinding issue

I'm using a RadGridView (Telerik). I'm trying to make a column editable only for certain rows, but what I'm trying doesn't seem to be working and I'm not sure how to do it.
My grid is this:
<telerik:RadGridView HorizontalAlignment="Left" Margin="12,12,12,12" Name="radGridView1" VerticalAlignment="Top" ItemsSource="{Binding FeedList}" ShowGroupPanel="False" AutoGenerateColumns="False" ShowInsertRow="True" EditTriggers="Default">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn Header="Feed" DataMemberBinding="{Binding Path=Name}" Width="150" IsReadOnly="{Binding Path=ReadOnly}" />
<telerik:GridViewDataColumn Header="Url" DataMemberBinding="{Binding Path=Url}" Width="*"/>
</telerik:RadGridView.Columns>
</telerik:RadGridView>
The bound object has a property, but the Path for the IsReadOnly binding is relative to the DataContext for the form and not the bound object. How would I make it relative to the bound object in this case?
In case anyone comes across this on a search. The answer is the GridView's datacontext is bound to the collection it's displaying and doesn't have access to the Window or UserControl's datacontext.
Thomas Levesque has a blog entry on the subject. He puts together a BindingProxy class that you can use to pass in the datacontext to the radgridview.
http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
Intellisense must have been messed up. Somehow missed the IsReadOnlyBinding property of GridViewDataColumn, which does exactly what I want. Not sure why IsReadOnly couldn't do it, though.

Sorting a WPF DataGrid, MVVM style

I'm trying to get sorting to work with a WPF Toolkit DataGrid. My DataGrid's rows are instances of view models. The row's view model exposes a view model for each column. Each column is data templated to a different user control. This is what my DataGrid's column declarations look like:
<tk:DataGrid.Columns>
<tk:DataGridTemplateColumn Header="Name" MinWidth="150" Width="150">
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Path=NameViewModel}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Data Dependencies" MinWidth="350" Width="Auto">
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Path=DependenciesViewModel}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
</tk:DataGrid.Columns>
Name is bound to a view model that is data templated with a user control that displays the name as a text block. It also displays some other graphical information, which is why it's displayed in a user control.
The problem with doing it this way is that I lose the ability to sort the Name column. I was hoping that implementing IComparable<T> on the row view model that exposes the Name view model would do the trick, but it doesn't look like the WPF data grid cares that it implements IComparable<T>.
Does anyone have any suggestions as to how best to tackle this?
This answer was what I was looking for.

Problem with DataTemplate and ObjectDataProvider refresh

I have a problem with a edit templete of cell in a WPF datagrid (WPF Toolkit). The template is builded with a ComboBox and the ItemsSource of
ComboBox are loaded at runtime.
This is the mean code...
<ObjectDataProvider x:Key="dataValuesProvider" MethodName="GetValues" />
<toolkit:DataGrid
ItemsSource="{Binding Path=MyItems}">
<toolkit:DataGridTemplateColumn
Header="Property1">
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Property1, ValidatesOnDataErrors=true}"/>
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
<toolkit:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox
SelectedValue="{Binding Path=Property1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
IsEditable="True"
IsSynchronizedWithCurrentItem="False"
ItemsSource="{Binding Source={StaticResource dataValuesProvider}, Mode=OneWay}"
/>
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellEditingTemplate>
</toolkit:DataGridTemplateColumn></toolkit:DataGrid>
Now, I have this problem.
I have to update the dataValuesProvider with different value on each rows. Then I have insert a reset of dataValuesProvider (dataValuesProvider=null) on selectionchanged event of datagrid.
(The dataValuesProvider will load after a input on a specific cell of the selected row).
This is the problem: when I reset the dataValuesProvider (on selectionchanged of a new row) it's modified the SelectedValue of ComboBox and the Property1 of previous row is cleared.
I think that there is this behavior becouse the editing template of cell not update the binding associations until I edit the cell. It's right?
How can I do to avoid this problem?
I have not yet resolved
however I have defined a simple project that show the problem.
You can download it from this link: http://pollosky.it/wp-content/uploads/2009/12/ObjectProviderTest.zip
Try to selectvalue from the second cell of the first row and then go to the second row. The value of property of first row is cleared!
How can I do?

Resources