Click here to Skip to main content
15,887,302 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
This is probably easier to show in code than to ask in English.

I have a list in my view-model, something like this:

public class CostItems
{
	public string Name { get; set; } "";
	
	public double UnitCost { get; set; } = 0.0;
	
	public bool UnitCostFixed { get; set; } = false;
}


public List<CostItem> CostItems = new List<CostItem>();


And my XAML to display this is something like this:

<DataGrid Grid.Row="1" Grid.Column="0" ItemsSource="{Binding CostItems}"
	AutoGenerateColumns="False"
	HeadersVisibility="Column"
	SelectionUnit="Cell" SelectionMode="Single">
	<DataGrid.Columns>
		<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
		<DataGridTextColumn Header="Unit Cost">
			<DataGridTextColumn.Binding>
				<Binding Path="UnitCost" UpdateSourceTrigger="LostFocus">
					<Binding.ValidationRules>
						<u:CurrencyNonNegativeValidator/>
					</Binding.ValidationRules>
					<Binding.Converter>
						<u:CurrencyConverter/>
					</Binding.Converter>
				</Binding>
			</DataGridTextColumn.Binding>
		</DataGridTextColumn>
	</DataGrid.Columns>
</DataGrid>


What I am wanting to do is bind the IsReadOnly property of the DataGridTextColumn that displays the UnitCost to the UnitCostFixed property of the same item in the list.

I'm guessing I need some form of RelativeSource binding but can't work it out.

How do I do this?

What I have tried:

I've tried looking at the visual tree but it seems not to show enough detail (i.e. it stops at the DataGrid.

I have also tried increasing the debug info coming from the binding engine by setting :
diag:PresentationTraceSources.TraceLevel="High"
but don't seem to be getting much that is helping me.
Posted
Updated 31-Mar-20 1:20am
Comments
[no name] 31-Mar-20 4:17am    
It's not logical: you want to tie a column property to a value in a "row" (i.e. item). This relates to the "cell".
Patrick Skelton 31-Mar-20 7:14am    
Thanks for the reply. You are, of course, right. I realised soon after posting that what I was attempting just didn't make sense. I held back on a reply until I had got something that works, which I have now posted.

1 solution

This seems to do the trick. What I do is use a template column instead of a plain text column. Now I can swap templates for each individual cell based on properties to which that row in the grid are bound. So I then simply have one editable version of the template and one that is read-only.

<DataGrid ItemsSource="{Binding CostItems}"
	HeadersVisibility="Column"
	SelectionUnit="Cell"
	SelectionMode="Single">

	<DataGrid.Resources>
		<DataTemplate x:Key="UnitCostAllowModifyTemplate">
			<TextBox IsReadOnly="False" IsTabStop="True">
				<Binding Path="UnitCost" UpdateSourceTrigger="LostFocus"/>
			</TextBox>
		</DataTemplate>
		<DataTemplate x:Key="UnitCostBlockModifyTemplate">
			<TextBox IsReadOnly="True" IsTabStop="False">
				<Binding Path="UnitCost"/>
			</TextBox>
		</DataTemplate>
	</DataGrid.Resources>

	<DataGrid.Columns>
		<DataGridTextColumn Header="Name" Binding={Binding Name}"/>
		<DataGridTemplateColumn Header="Unit Cost">
			<DataGridTemplateColumn.CellTemplate>
				<DataTemplate>
					<ContentControl Content="{Binding .}">
						<ContentControl.Style>
							<Style TargetType="{x:Type ContentControl}">
								<Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
								<Setter Property="ContentTemplate" Value="{StaticResource UnitCostAllowModifyTemplate}" />
								<Style.Triggers>
									<DataTrigger Binding="{Binding UnitCostFixed}" Value="False">
										<Setter Property="ContentTemplate" Value="{StaticResource UnitCostBlockModifyTemplate}" />
									</DataTrigger>
								</Style.Triggers>
							</Style>
						</ContentControl.Style>
					</ContentControl>
				</DataTemplate>
			</DataGridTemplateColumn.CellTemplate>
		</DataGridTemplateColumn>
	</DataGrid.Columns>
</DataGrid>


Top Tip I found on the internet is to use a dummy converter on any binding you can't debug. Then you can break in the debugger and see exactly what object the binding is getting.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900