#c# #wpf #xaml #wpfdatagrid
#c# #wpf #xaml #wpfdatagrid
Вопрос:
У меня есть сетка данных WPF, которую я заполняю с помощью
var allLines = from Lines in ctx.InvoiceLines join PerPs in ctx.ProductsViews on Lines.ProductCode equals PerPs.ProductCode
where (Lines.BranchNo == BrNo) amp;amp; (Lines.Docket == Docket)
select new { Lines.ProductCode, Lines.Description, Lines.Inv_Quantity, Lines.Grn_Quantity,
Lines.Inv_Price,Lines.Grn_Price,Lines.Inv_Total, Lines.Grn_Total, Lines.AnalCode,
Lines.Vat_Rate, Lines.GrnNo,Lines.Comment , PerPs.OuterUnits};
dgGrid.ItemsSource = allLines;
Я хочу использовать двустороннюю привязку для обновления базы данных при изменении любого из значений или при добавлении новой строки. Возможно ли это?
Мой код xaml
<DataGrid Grid.Row="3" x:Name="dgGrid" DataContext="{Binding}" FontSize="16" HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible" SelectionUnit="FullRow" SelectionMode="Extended" AutoGenerateColumns="False"
SelectionChanged="dgGrid_SelectionChanged" >
<DataGrid.Columns>
<DataGridTextColumn Width="Auto" Header="ProductCode" Binding="{Binding ProductCode, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="250" Header="Description" Binding="{Binding Description, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" FontSize="14"/>
<DataGridTextColumn Width="61" Header="Inv_Quantity" Binding="{Binding Inv_Quantity, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="63" Header="Grn_Quantity" Binding="{Binding Grn_Quantity, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="59" Header="Inv_Price" Binding="{Binding Inv_Price, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="61" Header="Ord_Price" Binding="{Binding Grn_Price, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="72" Header="Inv_Total" Binding="{Binding Inv_Total, Converter={StaticResource Currency}, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="74" Header="Grn_Total" Binding="{Binding Grn_Total, Converter={StaticResource Currency}, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="58" Header="AnalCode" Binding="{Binding AnalCode, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="40" Header="Vat_Rate" Binding="{Binding Vat_Rate, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="Auto" Header="GrnNo" Binding="{Binding GrnNo, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="Auto" Header="Comment" Binding="{Binding Comment, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Width="Auto" Header="PerP" Binding="{Binding OuterUnits}" IsReadOnly="True"/>
</DataGrid.Columns>
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightSteelBlue"/>
</DataGrid.Resources>
</DataGrid>
Когда я запускаю этот код, все столбцы, кроме PerP, пусты.
Я совершенно не понимаю, как сделать это наилучшим образом, поэтому любая помощь будет очень признательна.
Ответ №1:
Все Bindings
для вашего DataGridTextColumn
столбца, кроме столбца «PerP», указывают путь дважды. Например:
<DataGridTextColumn Width="Auto" Header="ProductCode" Binding="{Binding ProductCode, Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
Здесь вы Binding
сначала указываете путь, который должен быть «ProductCode», а затем также указываете его как «IsSelected». Поскольку для объектов в коллекции, которые вы привязываете к сетке, нет свойства «IsSelected», если вы запустите это в отладчике, вы должны увидеть ошибки привязки в окне вывода. Если вы удалите Path=IsSelected
для этих привязок, значения столбцов должны быть привязаны правильно.
Ваш источник данных представляет собой коллекцию анонимного типа, поэтому var
это необходимо, но, как говорили другие, двусторонняя привязка к этой коллекции не будет работать для обновлений обратно к источнику.
Комментарии:
1. Есть ли другой способ сделать это, который будет поддерживать двустороннюю привязку для обновлений?
2. Да, путем привязки к экземплярам фактического объекта, который вы хотите обновить, который в вашем случае будет объектами, отслеживаемыми Entity Framework. Я предполагаю, что в конечном итоге вы хотите, чтобы изменения сохранялись обратно в базу данных, поэтому имеет смысл, чтобы обновления влияли на объекты EF, которые выполняют отслеживание изменений, чтобы позже все изменения можно было сбросить в базу данных.
3. Есть ли у вас ссылка на какие-либо сайты, которые показали бы, как это можно сделать?
4. Спасибо, Стив, это действительно хорошее видео, я думаю, это именно то, что мне было нужно. 🙂
5. @Steve Rowbotham, у меня странное чувство от этого видео, как будто я в параллельной вселенной. Я никогда не получаю источник данных при создании модели EF. Я думал, что источники данных предназначены только для старомодных табличных адаптеров.
Ответ №2:
Ваша allLines
переменная является перечислимой анонимного типа. В C # анонимные типы доступны только для чтения — свойства нельзя редактировать, а изменения нельзя сохранить.
Попробуйте выполнить свой запрос:
var allLines =
from Lines in ctx.InvoiceLines
join PerPs in ctx.ProductsViews on Lines.ProductCode equals PerPs.ProductCode
where (Lines.BranchNo == BrNo) amp;amp; (Lines.Docket == Docket)
select Lines;
dgGrid.ItemsSource = allLines.ToList();
Комментарии:
1. Вместо того, чтобы проецировать результаты вашего запроса в коллекцию анонимного типа (т. Е. С использованием
new {...}
), Выберите фактические строки, как показал Пол выше, поскольку они должны отслеживать внесенные в них изменения.
Ответ №3:
Если переменной «allLines» является a DataTable
, вы можете просто установить для вашей сетки AutoGenerateColumns
данных значение true .
Вам также не нужно использовать свойство «DataContext», а вместо него «ItemsSource».
Что-то вроде этого:
<DataGrid ItemsSource="{Binding Path=allLines.DefaultView}" ... />
Чтобы обновить базу данных при изменениях, вызовите Update()
метод вашей таблицы данных, например, нажав кнопку «Сохранить».
Если «allLines» не является объектом данных, то удалите это адское ключевое слово «var» и сообщите нам истинную природу переменной =)
Комментарии:
1. Когда я использую ItemsSource, DG пуст. Я не знаю, какой тип данных allLines на самом деле
2. Из кода довольно ясно, что переменная в левой части присваивания не является объектом данных, так что это не имеет значения. Очевидно, что это коллекция анонимного типа, поэтому необходим var.