I have a very tricky situation where I am binding data to telerik radgridview where everything works until I try and bind the visibility of one checkbox column based on the the check value of another of the columns. I have tried the following:
<telerik:RadGridView ShowGroupPanel="False" AutoGenerateColumns="False" ItemsSource="{Binding ParametersFilterConfigurations}">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn IsFilterable="False" IsGroupable="False" IsSortable="False" DataMemberBinding="{Binding FilterElementName}" Header="Parameter Name" />
<telerik:GridViewCheckBoxColumn IsFilterable="False" IsGroupable="False" IsSortable="False" DataMemberBinding="{Binding CanView}" Header="Viewable"/>
<telerik:GridViewCheckBoxColumn IsVisible="{Binding CanView}" IsFilterable="False" IsGroupable="False" IsSortable="False" DataMemberBinding="{Binding CanFilterBy}" Header="Filterable" />
</telerik:RadGridView.Columns>
</telerik:RadGridView>
When I run this WPF attempts to locate the IsVisible="{Binding CanView" of the last column from the main datacontext and offcourse fails with the following:
System.Windows.Data Error: 40 : BindingExpression path error: 'CanView' property not found on 'object' ''MainWindow' (Name='')'. BindingExpression:Path=CanView; DataItem='MainWindow' (Name=''); target element is 'GridViewCheckBoxColumn' (HashCode=53813616); target property is 'IsVisible' (type 'Boolean')
How can I solve this? Please help.
I suggest using a cell template for the "Filterable" column. Since the "CanView" property changes per row, there's no way you can bind another entire column's visibility to that. What you can do is always show the column, but show/hide a checkbox in that column as needed. Ie, something like this:
<telerik:GridViewColumn>
<telerik:GridViewColumn.CellTemplate Header="Filterable">
<DataTemplate>
<CheckBox Visibility="{Binding CanView,Converter={StaticResource BoolToVisConverter}"
IsChecked="{Binding CanFilterBy}"
/>
</DataTemplate>
</telerik:GridViewColumn.CellTemplate>
</telerik:GridViewColumn>
Related
I have tried to update ItemSource of RadComboBox using ElementName property in Binding but when I use RelativeSource it is working as expected.
What is the difference.Can anyone please tell me.
<telerik:RadGridView Name="DesiredCapabilitiesGrid" RowIndicatorVisibility="Collapsed" AllowDrop="False" CanUserDeleteRows="True ShowGroupPanel="False" Height="Auto" Width="Auto"ItemsSource="{Binding DesiredCapabilities,Mode=TwoWay}"
GroupRenderMode="Flat" NewRowPosition="Bottom" Loaded="DesiredCapabilitiesGrid_Loaded">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn Header="Property Names" Width="2*" IsSortable="True" DataMemberBinding="{Binding DesiredCapabilityName}">
<telerik:GridViewDataColumn.CellEditTemplate>
<DataTemplate>
<telerik:RadComboBox ItemsSource="{Binding Path=DataContext.ConsiderDesiredCapabilites,ElementName="DesiredCapabilitiesGrid"}" IsEditable="True"></telerik:RadComboBox>
</DataTemplate>
</telerik:GridViewDataColumn.CellEditTemplate>
</telerik:RadGridView.Columns>
</telerik:RadGridView>
There is no element named DesiredCapabilitiesGrid in the same namescope as the RadComboBox in the CellEditTemplate. That's why the binding fails.
The RadComboBox is added to the visual tree and has visual ancestors though. That's why setting a RelativeSource work. Please refer to the link for more information about namescopes.
I have an Xceed DataGrid with an EditTemplate defined for the grid.
The grid shows a listing of items bound to a collection with about 6 columns and the EditTemplate is a TextBox control for entering a quantity. I want the IsReadOnly property to be bound to a different property so that the item has a serial number, IsReadOnly will be set to true so the user cannot enter a value. I want to bind to the SerialNum property within the same collection and pass it to a converter to return the true/false value. I've got the converter written; however, I'm having issues binding to the property to pass to the converter.
My DataGridCollectionViewSource is simple enough:
<xcdg:DataGridCollectionViewSource x:Key="transferItems" Source="{Binding TransferItems}" />
TransferItems is set in my ViewModel and all of the columns get properly bound.
For all of my generic display columns, they are being properly displayed via:
<xcdg:Column Title="Serial No." AllowSort="False" FieldName="SerialNum" />
My issue is in defining the xcgd:CellEditor template and I'm pretty sure my issue is around the RelativeSource. I've tried many different combinations trying to get the TransferItems.SerialNum property from my ViewModel, but no combination is working.
This is what I currently have:
<xcdg:Column Title="Xfer Qty Good" TextWrapping="Wrap" ReadOnly="False" Width="50" AllowGroup="False" AllowSort="False" FieldName="TransferQtyGood">
<xcdg:Column.CellEditor>
<xcdg:CellEditor>
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<TextBox x:Name="QtyGood" Margin="2,2,2,2" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{xcdg:CellEditorBinding}" IsReadOnly="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type xcdg:DataGridCollectionViewSource}}, Path=DataContext.TransferItems.SerialNum, Converter={StaticResource serialToEnabledConverter}}"
/>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
</xcdg:Column.CellEditor>
</xcdg:Column>
Which gives the runtime error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Xceed.Wpf.DataGrid.DataGridCollectionViewSource', AncestorLevel='1''. BindingExpression:Path=DataContext.TransferItems.SerialNum; DataItem=null; target element is 'TextBox' (Name='QtyGood'); target property is 'IsReadOnly' (type 'Boolean')
I understand what the error is telling me, but I'm just getting the proper RelativeSource path. I've read some of the helpful posts here on the enumerations for RelativeSource and still am missing something.
Just in case someone is having this issue, I was able to finally get the binding working in this manner. The key is defining the correct RelativeSource path:
<TextBox x:Name="QtyGood" Margin="2,2,2,2" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{xcdg:CellEditorBinding}" GotFocus="Qty_GotFocus" LostFocus="Qty_LostFocus"
IsReadOnly="{Binding RelativeSource={RelativeSource AncestorType={x:Type xcdg:DataRow}}, Path=DataContext.SerialNum, Converter={StaticResource serialToEnabledConverter}}"
/>
I have DataGrid which has a column that is to be shown/hidden depending on a property. I have had no luck in showing/hiding the column, so we ended up taking the column out and put it in a separate DataGrid and place the second DataGrid inside an Expander.
The header of the second DataGrid is bound the the DataContext of the Expander (or DataGrid - same effect, have also tried binding it to the containing usercontrol).
<Expander ExpandDirection="Right" Style="{DynamicResource ExpanderDirectionRight}" IsExpanded="{Binding ShowLaterDate}">
<DataGrid AutoGenerateColumns="False" AlternationCount="2" SelectionMode="Single" ItemsSource="{Binding Rows, UpdateSourceTrigger=PropertyChanged}" CanUserDeleteRows="True" CanUserAddRows="False" CanUserResizeColumns="False" SnapsToDevicePixels="True" Visibility="{Binding Rows.HasContent, Converter={StaticResource BooleanToVisibilityConverter}}" HorizontalAlignment="Left" SelectedIndex="{Binding SelectedIndex, ElementName=BudgetDataGrid}">
<DataGrid.Columns>
<DataGridTemplateColumn CellTemplate="{StaticResource LaterDataTemplate}" Width="{StaticResource WidthOfValueColumns}">
<DataGridTemplateColumn.Header>
<Grid Margin="{StaticResource MarginOfTextBox}">
<userControls:DateOrAgeEditor Date="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Expander}}, Path=DataContext.LaterDate, UpdateSourceTrigger=LostFocus}" DateOfBirth="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Expander}}, Path=DataContext.DateOfBirth}" TabIndex="11"/>
</Grid>
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Expander>
This is all good an well.
Problem:
The bound value is shown when the usercontrol is displayed. BUT ONLY if the Expander is expanded!
If the Expander is collapsed when the usercontrol is displayed this is printed to output:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.Expander', AncestorLevel='1''. BindingExpression:Path=DataContext.DateOfBirth; DataItem=null; target element is 'DateOrAgeEditor' (Name='UserControl'); target property is 'DateOfBirth' (type 'DateTime')
System.Windows.Data Warning: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.Expander', AncestorLevel='1''. BindingExpression:Path=DataContext.LaterDate; DataItem=null; target element is 'DateOrAgeEditor' (Name='UserControl'); target property is 'Date' (type 'DateTime')
When the Expander is then expanded the binding is not updated and continues to be 'broken'.
Question:
How do I get the binding to bind correctly even when the Expander is not initially expanded?
Just found a way of binding the Visibility of my column (http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/) this has however reintroduced the same problem as the expander. But easy to fix, just use the same kind of binding for the header-content as for the visibility.
I am using the Telerik framework for creating a RadGridView with child elements in Silverlight 4.
<telerikGrid:RadGridView x:Name="itemsGrid" Grid.Row="1" AutoGenerateColumns="{Binding AutoGenerateColumn, Mode=TwoWay}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" ItemsSource="{Binding Items, Mode=TwoWay}" CanUserInsertRows="True" ShowInsertRow="True" CanUserDeleteRows="True">
<telerikGrid:RadGridView.Columns>
<telerikGrid:GridViewToggleRowDetailsColumn />
<telerikGrid:GridViewDataColumn Header="Item 1" DataMemberBinding="{Binding Item1}" UniqueName="Item1" />
<telerikGrid:GridViewComboBoxColumn Header="Group" UniqueName="Group"
ItemsSource="{Binding Groups.Items}" SelectedValueMemberPath="GroupId" DisplayMemberPath="GroupNames" />
<telerikGrid:GridViewComboBoxColumn Header="Supplier" UniqueName="Supplier"
ItemsSource="{Binding Suppliers}" SelectedValueMemberPath="CompanyS" DisplayMemberPath="CompanyName" />
<telerikGrid:GridViewDataColumn Header="Not in use" DataMemberBinding="{Binding inUse}" UniqueName="inUse" />
</telerikGrid:RadGridView.Columns>
<telerikGrid:RadGridView.ChildTableDefinitions>
<telerikGrid:GridViewTableDefinition />
</telerikGrid:RadGridView.ChildTableDefinitions>
<telerikGrid:RadGridView.HierarchyChildTemplate>
<DataTemplate>
<StackPanel>
<telerikGrid:RadGridView x:Name="childGrild" Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding ChildList}" CanUserInsertRows="True" CanUserDeleteRows="True" IsReadOnly="False" ShowInsertRow="True" ShowGroupPanel="False">
<telerikGrid:RadGridView.Columns>
<telerikGrid:GridViewDataColumn Header="Part S" DataMemberBinding="{Binding PartS}" UniqueName="PartS" />
<telerikGrid:GridViewComboBoxColumn Header="Tools" ItemsSource="{Binding ElementName=control, Path=DataContext.Tools}" DataMemberBinding="{Binding PartS}" SelectedValueMemberPath="Id" DisplayMemberPath="Name" />
</telerikGrid:RadGridView.Columns>
</telerikGrid:RadGridView>
</StackPanel>
</DataTemplate>
</telerikGrid:RadGridView.HierarchyChildTemplate>
</telerikGrid:RadGridView>
As you can see, each row in the grid has a child GridView, the problem is however that i cant get the Combobx in the gridview to display any data, its always empty. If i move it outside the child tempate it works fine, and the Items which are in the Tools list is shown.
To access the list, which is a property of the controls datacontext, i gave the control a Name (control), and used Path=DataContex.Tools, which i read should work.
Anyone has any idea why the ComboBox is not populated with data? I have checked that all the propertie names are correct, and that there actually are data there to show.
RadGridView and ElementName don't mix very well. In your case, the 'control' element can't be found. You could use a DataContextProxy as shown in the link. It solved an issue I had that was similar.
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.