I have a WPF DataGrid control that is binding to a collection of objects. Everything is rendering on-screen as it should be.
ToString() has been overridden due to requirements elsewhere in the application.
The issue is that, when read by a screen reader (such as Microsoft's built-in Narrator), or when inspected via a tool like AccChecker / Inspect, the control's name is the overridden ToString value.
I want to be able to specify a descriptive name for the screen reader, but I can't find a method of doing so. I've tried setting AutomationProperties.Name, AutomationProperties.ItemType, and so forth, but none of the properties in AutomationProperties seem to have the desired effect.
Optimally, I'd be able to do this for both the data item itself, and also for the individual members of the columns.
Here's a complete demo of the issue I'm experiencing:
<DataGrid x:Name="dgTest" ItemsSource="{Binding}" AutoGenerateColumns="false" AutomationProperties.Name="Test">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name" IsReadOnly="True" Width="2*" AutomationProperties.Name="Test2">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="ID" IsReadOnly="True" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Id}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And the code:
public class FooItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Concat(Id.ToString(), " : ", Name);
}
}
public partial class MainWindow : Window
{
public readonly List<FooItem> fooList = new List<FooItem>();
public MainWindow()
{
fooList.Add(new FooItem { Id = Guid.NewGuid(), Name = "Test 1" });
fooList.Add(new FooItem { Id = Guid.NewGuid(), Name = "Test 2" });
fooList.Add(new FooItem { Id = Guid.NewGuid(), Name = "Test 3" });
InitializeComponent();
dgTest.DataContext = fooList;
}
}
And just for completeness, here's a screenshot of Inspector.
full size image
I found a solution... I had to use a style on DataGrid.ItemContainerStyle and DataGridTemplateColumn.HeaderStyle to set AutomationProperties.Name.
Ex:
<DataGrid x:Name="dgTest" ItemsSource="{Binding}" AutoGenerateColumns="false" AutomationProperties.Name="Test">
<DataGrid.ItemContainerStyle>
<Style>
<Setter Property="AutomationProperties.Name" Value="Row Item" />
</Style>
</DataGrid.ItemContainerStyle>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name" IsReadOnly="True" Width="2*" AutomationProperties.Name="Test2">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="ID" IsReadOnly="True" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Id}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Related
I'm working on a program for playing audio files and have ran into some issues with one of my DataGrids. Basically it's meant to allow the user change settings for it (Listen, repeat and volumes for example).
For this I have made my own UserControl, which is being dynamically added via DataTemplates in XAML. So first of all here's some context;
SoundFile.cs (public class)
Class that has file-related properties such as Name, Path, Category and Volumes.
SoundLibrary.cs (public static)
This is a static class which keeps track of all SoundFiles inside an ObservableCollection, this is the collection used to populate my DataGrids.
SoundControl.cs (UserControl)
This is my UserControl which consists of a few buttons, it has a property for SoundFile which is what I'm confused as to how to set and/or properly access.
This is how my DataGrid is defined;
<DataGrid
x:Name="MyDataGrid"
Margin="0,0,0,36"
AlternationCount="2"
AutoGenerateColumns="False"
IsReadOnly="True"
ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" />
<DataGridTemplateColumn Header="Listen Volume">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Slider
Margin="5"
Maximum="100"
Minimum="0"
Value="{Binding DataContext.ListenVolume, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Settings">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:SoundControl x:Name="SoundController" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Progress">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ProgressBar
Maximum="100"
Minimum="0"
Visibility="Visible"
Value="50" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And here's how I bind it in code behind;
MyDataGrid.ItemsSource = SoundLibrary.Library;
for (int i = 0; i < MyDataGrid.Items.Count; i++)
{
SoundFile sf = (SoundFile)MyDataGrid.Items.GetItemAt(i);
Debug.WriteLine(sf.FilePath);
}
Doing that I can access the SoundFile as expected, however I'm not sure how to access the SoundFile through the SoundControl.
The SoundControl class is very simple;
public partial class SoundControl : UserControl
{
public SoundFile Sound { get; set; } = new SoundFile();
public SoundControl()
{
InitializeComponent();
ListenButton.IsToggled = Sound.Listen;
RepeatButton.IsToggled = Sound.Repeat;
}
private void GridButton_MouseUp(object sender, MouseButtonEventArgs e)
{
if (sender == ListenButton)
{
Sound.Listen = ListenButton.IsToggled;
MainWindow mainWindow = (MainWindow)Window.GetWindow(this);
mainWindow.UnsavedChanges = true;
}
if (sender == RepeatButton)
{
Sound.Repeat = RepeatButton.IsToggled;
MainWindow mainWindow = (MainWindow)Window.GetWindow(this);
mainWindow.UnsavedChanges = true;
}
if (sender == FolderButton)
{
Debug.WriteLine(Sound.FilePath);
//Sound.OpenDirectory();
}
}
}
Any pointers in the right direction would be much appreciated, still relatively new to data binding and using DataGrids... Thanks in advance!
The Sound property of the SoundControl should be a bindable property, i.e. dependency property:
public static readonly DependencyProperty SoundProperty =
DependencyProperty.Register(
nameof(Sound), typeof(SoundFile), typeof(SoundControl));
public SoundFile Sound
{
get { return (SoundFile)GetValue(SoundProperty); }
set { SetValue(SoundProperty, value); }
}
You would bind it to the current SoundFile item of the DataGrid row like this:
<DataGridTemplateColumn Header="Settings">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:SoundControl Sound="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I have a DataGrid with 3 column inside: Name -DataGridTextColumn, Value-DataGridTextColumn, ParamJson - DataGridTemplateColumn with combobox and has a ICollectionView of ParameterGrid as a source.
There is a ViewModel that provides ICollectionView of ParameterGrid. ParameterGrid contains 4 parameters: Name, Value, ParamJson, SelectedParamJson.
I need to handle all rows of DataGrid, so i use the command that get all dataGrid as a Command Parameter and than iterate over DataGrid.Items (I could use directly ICollectionView?).
The question is How to bind properly SelectedItem in Combobox in DataGrid to SelectedParamJson?
Xaml:
<DataGrid Grid.Row="0"
x:Name="parametersGridView"
AutoGenerateColumns="False"
VerticalScrollBarVisibility="Visible"
CanUserAddRows="False"
ItemsSource="{Binding PropertiesGrid}"
Margin="5"
AlternatingRowBackground="LightGoldenrodYellow">
<DataGrid.Columns>
<DataGridTextColumn Header="Name"
Binding="{Binding Path=Name}"
IsReadOnly="True" />
<DataGridTextColumn Header="Value"
Binding="{Binding Path=Value}" />
<DataGridTemplateColumn Header="Parameter" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox MinWidth="100"
MaxWidth="150"
ItemsSource="{Binding Path=ParamsJson}"
SelectedItem="{Binding Path=SelectedParamJson, RelativeSource={RelativeSource AncestorType=DataGrid}}"
StaysOpenOnEdit="True"
IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid > <DataGrid Grid.Row="0"
x:Name="parametersGridView"
AutoGenerateColumns="False"
VerticalScrollBarVisibility="Visible"
CanUserAddRows="False"
ItemsSource="{Binding PropertiesGrid}"
Margin="5"
AlternatingRowBackground="LightGoldenrodYellow">
<DataGrid.Columns>
<DataGridTextColumn Header="Name"
Binding="{Binding Path=Name}"
IsReadOnly="True" />
<DataGridTextColumn Header="Value"
Binding="{Binding Path=Value}" />
<DataGridTemplateColumn Header="Parameter" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=ParamsJson}"
SelectedItem="{Binding Path=SelectedParamJson, RelativeSource={RelativeSource AncestorType=DataGrid}}"
StaysOpenOnEdit="True"
IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid >`
ViewModel
class DataGridViewModel : DependencyObject
{
public DataGridViewModel()
{
var data = new DataEmulator();
PropertiesGrid = CollectionViewSource.GetDefaultView(data.GetCommonParameters());
}
public ICollectionView PropertiesGrid
{
get { return (ICollectionView)GetValue(PropertiesGridProperty); }
set { SetValue(PropertiesGridProperty, value); }
}
public static readonly DependencyProperty PropertiesGridProperty =
DependencyProperty.Register("PropertiesGrid", typeof(ICollectionView), typeof(DataGridViewModel), new PropertyMetadata(null));
public ICommand TestCommand
{
get
{
return new RelayCommand
{
ExecuteAction = a =>
{
// here SelectedParamJson should be as Selected in combobox,
// but it is always null because of the wrong binding
},
CanExecutePredicate = p =>
{
return true;
}
};
}
}
}
public class ParameterGrid
{
public string Name { get; set; }
public string Value { get; set; }
public List<SamResult> ParamsJson { get; set; }
public SamResult SelectedParamJson { get; set; }
}
If you want to bind to the SelectedParamJson property that is defined in the same class as the ParamsJson property, you should not set the RelativeSource property to anything at all:
ItemsSource="{Binding Path=ParamsJson}"
SelectedItem="{Binding Path=SelectedParamJson}"
You should also move the ComboBox to the CellEditingTemplate of the DataGridTemplateColumn.
The thing is you have to define <DataGridTemplateColumn.CellEditingTemplate>, where you should do all bindings and <DataGridTemplateColumn.CellTemplate>, that present value when the cell is not active.
That seems to be strange that you could not bind everything inside <DataGridTemplateColumn.CellTemplate>, because you have to do an additional klick to activate combobox.
Xaml that works for me:
<DataGridTemplateColumn Header="Parameter" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=SelectedParamJson}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox MinWidth="100"
MaxWidth="150"
ItemsSource="{Binding Path=ParamsJson}"
SelectedItem="{Binding Path=SelectedParamJson}"
StaysOpenOnEdit="True"
IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
your ancestor is not the datagrid its the datarow you want to get the datacontext from.
so you made a collection view of some source collection like list, this means every row in your Datagrid repesents a IJsonObject Object and there you should have your Collection for the ComboBox Column defined. Like a List that you can bind to the Column and in Turn you can have a IJsonProperty field that you can bind to the selected Item.
So then you should get a Combobox filled with yout List Items and if you select one of them the IJsonProerty Field will be set to the selected Item.
I hope its understandable since I dont really got a code snippet right now.
This is my XAML code:
<ComboBox Grid.Row="0" Margin="5" ItemsSource="{Binding Path=Clvm.Categories}">
</ComboBox>
<GridSplitter Grid.Row="0" Height="3" />
<DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding Alvm.Artists}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" />
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Email" Binding="{Binding Email}" />
<DataGridComboBoxColumn Header="Category" SelectedItemBinding="{Binding Category}"
ItemsSource="{Binding Path=Clvm.Categories}" />
</DataGrid.Columns>
</DataGrid>
The ComboBox above is just for testing - I want to see if I can display all my Categories and it works well.
The DataGrid below is the control I really want. I want that Categories ComboBox as a column of the DataGrid. But the way I do it in the snippet obviously doesn't work as the data bindings for the columns are relative to the DataGrid's ItemsSource and not to the old DataContext. How can I switch it back for that binding?
The Control class:
public partial class ArtistManagementControl : UserControl {
public ArtistManagementControl() {
InitializeComponent();
IDatabase db = new MYSQLDatabase("Server = localhost; Database = ufo; Uid = root;");
SharedServices.Init(db);
Alvm = new ArtistListViewModel(SharedServices.GetInstance().ArtistService, SharedServices.GetInstance().CategoryService);
Clvm = new CategoryListViewModel(SharedServices.GetInstance().CategoryService);
this.DataContext = this;
}
public ArtistListViewModel Alvm {
get; private set;
}
public CategoryListViewModel Clvm {
get; private set;
}
}
The ViewModel for the categories:
public class CategoryListViewModel {
private ICategoryService categoryService;
public CategoryListViewModel(ICategoryService categoryService) {
this.categoryService = categoryService;
Categories = new ObservableCollection<CategoryViewModel>();
UpdateCategories();
}
public ObservableCollection<CategoryViewModel> Categories {
get; set;
}
public void UpdateCategories() {
Categories.Clear();
foreach(var cat in categoryService.GetAllCategories()) {
Categories.Add(new CategoryViewModel(cat));
}
}
}
Since DataGridComboBoxColumn or any other supported data grid columns are not part of visual tree of datagrid so they don't inherit the DataContext of datagrid. Since, they don't lie in visual tree so any try to get DataContext using RelativeSource won't work.
Solution - You can create a proxy element to bind the data context of window; use that proxy element to bind the ItemsSource of DataGridComboBoxColumn.
<Grid>
<Grid.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Grid.Resources>
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"></ContentControl>
<DataGrid x:Name="datagrid" Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding Alvm.Artists}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" />
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Email" Binding="{Binding Email}" />
<DataGridComboBoxColumn Header="Category" SelectedItemBinding="{Binding Category}"
ItemsSource="{Binding DataContext.Clvm.Categories, Source={StaticResource ProxyElement}}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
You can bind to the DataGrids DataContext by using an ElementName Binding:
<DataGrid x:Name="datagrid" Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding Alvm.Artists}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" />
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Email" Binding="{Binding Email}" />
<DataGridComboBoxColumn Header="Category" SelectedItemBinding="{Binding Category}"
ItemsSource="{Binding Path=DataContext.Clvm.Categories, ElementName=datagrid}" />
</DataGrid.Columns>
</DataGrid>
Note that you have to give the DataGrid a name for that to work.
Another option is to bind to an Ancestor. With this solution you dont have to give the DataGrid a name, but it is more complex:
<DataGridComboBoxColumn Header="Category" SelectedItemBinding="{Binding Category}"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.Clvm.Categories}" />
Let's say I have the following two classes in my model-folder:
public class Simple
{
public int Id { get; set; }
public string Display { get; set; }
public double Value1 { get; set; }
}
and
public class Extended : Simple
{
public double Value2 { get; set; }
public string Name { get; set; }
}
To display a collection of Simple I've created a UserControl which looks like:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}"
CanUserAddRows="False" CanUserDeleteRows="False">
<DataGrid.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="4,2"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Id" Width="Auto" SortMemberPath="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Display" Width="*" SortMemberPath="Display">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Display}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Value1" Width="*" SortMemberPath="Value1">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value1}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
The usage of this UserControl looks like:
<local:SEControl DataContext="{Binding Simples}"/>
Now I want to display a collection of Extended-Objects. My approach would now be to write another UserControl which just have two columns more than the other one.
My question now is: Is there a way to just write one UserControl which can handle Simple and Extended?
I also thought about a DataTemplate, but there I have to duplicate the logic too.
You can try to use Visibility.
Add the extended columns as here :
<DataGridTemplateColumn Visibility="{Binding IsExtended, Converter={StaticResource BoolToVis}, FallbackValue=Hidden}" Header="Test" Width="*" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Test}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
and using a converter you can switch whenever you need to show or not these columns.
So, when you change the ItemSource in order to contain Extended items, change also the IsExtended property to true and vice-versa.
Apologies in advance if I'm overlooking something - I'm still finding my feet working with Xaml rather than windows forms.
I'm trying to bind a data source to a DataGrid where one of the columns is a checkbox. My original solution worked fine for this, but required the user to double click the checkbox:
<Window x:Class="ExecBoxInvoices.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="507" Width="676">
<Grid Margin="0,0,0,51">
<DataGrid x:Name="InvoiceDG" HorizontalAlignment="Left" Height="165" Margin="134,251,0,0" VerticalAlignment="Top" Width="400" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Generate" Binding="{Binding Generate}" Width="80"/>
<DataGridTextColumn Header="Table_Number" Binding="{Binding Table_Number}" Width="120"/>
<DataGridTextColumn Header="Transaction_Date" Binding="{Binding Transaction_Date}" Width="175"/>
<DataGridTextColumn Header="Transaction_ID" Visibility="Hidden" Binding="{Binding Transaction_ID}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
The new solution for single click checkboxes is displayed below, but doesn't work (error is shown on the Binding="{Binding Generate}"):
<Window x:Class="ExecBoxInvoices.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="507" Width="676">
<Grid Margin="0,0,0,51">
<DataGrid x:Name="InvoiceDG" HorizontalAlignment="Left" Height="165" Margin="134,251,0,0" VerticalAlignment="Top" Width="400" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Generate" Width="60" Binding="{Binding Generate}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Table_Number" Binding="{Binding Table_Number}" Width="120"/>
<DataGridTextColumn Header="Transaction_Date" Binding="{Binding Transaction_Date}" Width="175"/>
<DataGridTextColumn Header="Transaction_ID" Visibility="Hidden" Binding="{Binding Transaction_ID}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
For reference, the code used to set the source is:
InvoiceDG.ItemsSource = recordCollection;
Where recordCollection is a list of:
class InvoiceRow
{
public bool Generate { get; set; }
public string Table_Number { get; set; }
public string Transaction_Date { get; set; }
public string Transaction_ID { get; set; }
public InvoiceRow(bool generate, string table_Number, string transaction_Date, string transaction_ID)
{
this.Generate = generate;
this.Table_Number = table_Number;
this.Transaction_Date = transaction_Date;
this.Transaction_ID = transaction_ID;
}
}
Try this:
<DataGridTemplateColumn Header="Generate" Width="60">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Generate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>