I have a DataGridTemplateColumn that is editable. I only want the user to be able to edit the content of a cell in this column if the business object satisfies some criterion. Suppose my business object implements INotifyPropertyChanged and has three properties: Name, Department, and Sales. Name and Department are strings, and Sales is a double.
I want the user to be able to edit the Sales value only if Department equals "Retail". Here's a datagrid I might use to do this:
<DataGrid ItemsSource="{Binding Path=MyTypeCollection}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=OneTime}" IsReadOnly="True" />
<DataGridTextColumn Header="Department" Binding="{Binding Path=Department, Mode=OneTime}" IsReadOnly="True" />
<DataGridTemplateColumn Header="Sales">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Sales, Mode=TwoWay}" Visibility="{Binding Path={StaticResource ResourceKey=IsRetail}}" />
<TextBlock Text="{Binding Path=Sales, Mode=OneWay}" Visibility="{Binding Path={StaticResource ResourceKey=IsNotRetail}}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Path=Sales, Mode=TwoWay}" Visibility="{Binding Path={StaticResource ResourceKey=IsRetail}}" />
<TextBlock Text="{Binding Path=Sales, Mode=OneWay}" Visibility="{Binding Path={StaticResource ResourceKey=IsNotRetail}}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I'm using a stack panel with two Text elements. I use a binding in the Visibility of the Text elements to toggle Text elements. If I have a row with a Department value that is not "Retail", I display a TextBlock in the Sales column whether the cell is in display mode or edit mode.
This seems like a clumsy solution to me. Is there some way I can prevent these types of cells from entering edit mode entirely? I only want to allow edit mode in the case that the Department is "Retail". Is this possible?
Edit: Adding code.
@Rachel. Thank you for your help. I want to paste in all of my datagrid XAML code to make sure I have everything right.
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=Data}">
<DataGrid.Resources>
<DataTemplate x:Key="TextBoxTemplate">
<TextBox Text="{Binding Path=Sales}" />
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Department" Binding="{Binding Path=Department, Mode=OneTime}" />
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=OneTime}" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ContentControl x:Name="salesControl">
<TextBlock Text="{Binding Sales}" />
</ContentControl>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Department}" Value="Retail">
<Setter TargetName="salesControl" Property="ContentTemplate" Value="{StaticResource TextBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Sales}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I've almost got this where I want it. When I click on a Sales
value in a Retail
row, a TextBox appears but it doesn't have a value in it (see here). I'm not sure why it doesn't have a value because the TextBox in the TextBoxTemplate specifies a binding. Do you know why this is?
Edit: I noticed one other problem with this solution, I can't actually edit the value in the Sales column. If I try, the value reverts to the original pre-edit value.