#wpf #data-binding #linq-to-sql #wpfdatagrid
#wpf #привязка данных #linq-to-sql #wpfdatagrid
Вопрос:
У меня есть приложение WPF с datagrid, которое я привязываю к пользовательскому запросу LINQ to SQL в моей ViewModel, который объединяет столбцы из двух разных таблиц:
public ICollectionView SetsView { get; set; }
public void UpdateSetsView()
{
var sets = (from s in dbContext.Sets
join o in dbContext.SetParts on s.ID equals o.SetID into g1
select new
{
s.ID,
s.SetNumber,
s.SetTitle,
s.SetType,
s.SetNotes,
s.SetUrl,
s.HaveAllParts,
s.NumberOfSets,
s.IsBuilt,
s.DateAdded,
s.LastModified,
UniqueParts = g1.Count(),
TotalParts = g1.Sum(o => o.Quantity)
}
);
SetsView = CollectionViewSource.GetDefaultView(sets);
}
Коллекция SetsView привязана к моей datagrid, и поскольку мне нужно иметь возможность редактировать значение SetNotes для любой строки и сохранять его обратно в таблицу Sets в моей базе данных, я добавил обработчик событий для CellEditEnding (CellEditEnding=»dgST_Sets_CellEditEnding») к определению DataGrid и создал этот столбец:
<DataGridTemplateColumn Header="Set Notes"
SortMemberPath="SetNotes"
Width="*">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SetNotes, Mode=OneWay}" Margin="5,0,5,0"
HorizontalAlignment="Stretch" VerticalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding SetNotes, Mode=OneWay}" Margin="5,0,5,0"
HorizontalAlignment="Stretch" VerticalAlignment="Center"
/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
Проблема в том, что когда я запускаю приложение и редактирую столбец Set Notes в любой строке, я не могу понять, как получить новое значение отредактированной ячейки из аргументов события. Я думал, что смогу преобразовать экземпляр EditingElement аргументов события в текстовое поле (см. обработчик ниже), но когда я запускаю приложение, редактирую строку и изменяю значение SetNotes, тип EditingElement — ContentPresenter, а не TextBox, и, хоть убейте, я не могу понять, как получить измененное значение.
private void dgST_Sets_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
string newValue = ((TextBox)e.EditingElement).Text;
//Code here to update table
}
Пожалуйста, помните, что я привязываюсь к пользовательскому запросу LINQ to SQL, поэтому это не проблема привязки классической модели. Также обратите внимание, что при привязке значения SetNotes в столбце моего шаблона у меня нет другого выбора, кроме как использовать Mode = OneWay, поскольку использование любого другого параметра приводит к ошибкам во время выполнения при доступе к свойству только для чтения — может ли это как-то быть проблемой?
Я потратил часы на это и бесконечно гуглил без радости — кто-нибудь может мне помочь, пожалуйста?
Ответ №1:
Это должно сработать:
private void dgST_Sets_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
ContentPresenter cp = e.EditingElement as ContentPresenter;
if (cp != null amp;amp; VisualTreeHelper.GetChildrenCount(cp) > 0)
{
TextBox textBox = VisualTreeHelper.GetChild(cp, 0) as TextBox;
if (textBox != null)
{
string newValue = textBox.Text;
}
}
}
Комментарии:
1. Большое спасибо mm8 — не могу поверить, что я не подумал о обходе визуального дерева, но это работает отлично.
2. действительно сожалею об этом, я думал, что сделал это, но, очевидно, не сейчас 🙂