Мой первый вопрос в StackExchange, так скажите мне, если я что-то сделаю неправильно.Настройка ItemSource в DataGridComboBoxColumn Использование отдельной таблицы базы данных
Я преобразовываю старый код winforms в WPF, и я склоняю их обоих по пути. Я был успешным большую часть времени, но я привязываю свою первую таблицу данных с привязкой данных. Кажется, что самое сложное преобразование, поскольку привязка обрабатывается в основном в xaml, а не в коде.
В качестве дополнительного примечания используется CSLA, который, насколько я понимаю, является структурой кода, подобной MVVM (все еще изучая, что это такое).
С небольшим количеством экспериментов мне удалось создать функционирующую сетку данных, но мне нужно реализовать один из столбцов как поле со списком. Он представлен в настоящее время как число (1-10), но мне нужно описание, которое идет с номером, который находится в другой таблице в базе данных.
Число, которое изначально отображалось перед переключением его в выпадающий список, было неосуществимым. Я хочу, чтобы это значение было выбранным в данный момент элементом в поле со списком.
Не можете размещать изображения, так вот моя попытка показывает структуру таблиц базы данных:
modreview
- reviewnum
- intcaseno
- newreferral
- screendate
- имеет право
- noneligibilityreason (это тот, чтобы сделать в ComboBox)
noneligreason (это субтаблица, который совпадет с noneligibilityreason)
- noneligreasonid
- noneligreasondesc
Код включает эту функцию Тион, который, кажется, чтобы создать коллекцию, которая должна быть, как мне кажется, ItemsSource:
NERList.GetNameValueList();
Что касается ItemsSource, я хочу все noneligreasondesc значений. Конечно, тогда возникает вопрос о том, чтобы нелимитируемый разум соответствовал неэлигрэзониду.Я нашел this example, который, кажется, делает то же самое, но без базы данных, используя классы вместо:
Я попытался повторить это, как я думал, что он должен работать здесь, в моем XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTestProject" x:Class="WpfTestProject.MainWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Window.Resources>
<local:caseviewDataSet x:Key="caseviewDataSet"/>
<CollectionViewSource x:Key="modreviewViewSource"
Source="{Binding modreview, Source={StaticResource caseviewDataSet}}"/>
<CollectionViewSource x:Key="noneligibilityViewSource"
Source="{Binding noneligreason, Source={StaticResource caseviewDataSet}}"/>
</Window.Resources>
<Grid DataContext="{StaticResource modreviewViewSource}">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DataGrid x:Name="modreviewDataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected"
ItemsSource="{Binding}"
EnableRowVirtualization="True"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="reviewnumColumn" Width="SizeToHeader" Header="reviewnum" Binding="{Binding reviewnum}"/>
<DataGridTextColumn x:Name="intcasenoColumn" Width="SizeToHeader" Header="intcaseno" Binding="{Binding intcaseno}"/>
<DataGridCheckBoxColumn x:Name="newreferralColumn" Width="SizeToHeader" Header="newreferral" Binding="{Binding newreferral}"/>
<DataGridTemplateColumn x:Name="screendateColumn" Width="Auto" Header="screendate">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding screendate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridCheckBoxColumn x:Name="eligibleColumn" Width="SizeToHeader" Header="eligible" Binding="{Binding eligible}"/>
<DataGridComboBoxColumn x:Name="noneligibilityreasonColumn" Width="SizeToHeader" Header="noneligibilityreason"
ItemsSource="{Binding Source={StaticResource noneligibilityViewSource}}"
SelectedValueBinding="{Binding noneligibilityreason}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
/>
</DataGrid.Columns>
</DataGrid>
</Grid>
И код позади:
using CslaFactoryBusinessObjects;
...
namespace WpfTestProject
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WpfTestProject.caseviewDataSet caseviewDataSet = ((WpfTestProject.caseviewDataSet)(this.FindResource("caseviewDataSet")));
// Load data into the table modreview. You can modify this code as needed.
WpfTestProject.caseviewDataSetTableAdapters.modreviewTableAdapter caseviewDataSetmodreviewTableAdapter = new WpfTestProject.caseviewDataSetTableAdapters.modreviewTableAdapter();
caseviewDataSetmodreviewTableAdapter.Fill(caseviewDataSet.modreview);
System.Windows.Data.CollectionViewSource modreviewViewSource = ((CollectionViewSource)(this.FindResource("modreviewViewSource")));
modreviewViewSource.View.MoveCurrentToFirst();
noneligibilityreasonColumn.ItemsSource = NERList.GetNameValueList();
}
}
}
Большая часть этого кода была сгенерирована, когда я перетаскивал данные из источников данных, но последняя строка в коде позади - это то место, где я думаю, что я должен был добавить ItemSource. Не уверен, что он принадлежит Loaded, но похоже, что все в порядке. Также не уверен, есть ли способ сделать это в XAML.
Я понимаю, что я дублировал настройки ItemsSource в XAML и коде, но никто не работает должным образом, поэтому я включил оба, чтобы показать, какие параметры я попробовал.
Наконец, я думаю, что должен показать старый код winforms, который я пытаюсь подражать в преобразовании WPF (не уверен, что этого достаточно кода). Я думаю, что он использует скрытый выпадающий настроить связывание, а затем добавляет его к столу:
//from Program.cs used in setupModRvwGrdHdr()
public static void ListControlBinding(ref UltraCombo comboBox, object lkupdataSource, string displayMember,
string valueMember, object objDataSource, string objProp) {
comboBox.DataSource = lkupdataSource;
comboBox.DisplayMember = displayMember;
if (!string.IsNullOrEmpty(valueMember))
comboBox.ValueMember = valueMember;
if (objDataSource != null)
comboBox.DataBindings.Add("Value", objDataSource, objProp);
}
//from the code for the specific winform
private void setupModRvwGrdHdr() {
cbNonEligReason.DataBindings.Clear();
grdModReviews.DataSource = bsModRvws;
Program.ListControlBinding(ref cbNonEligReason, NERList.GetNameValueList(), "Value", "Key", bsModRvws,
"NonEligibleReasonIDStr");
cbNonEligReason.DisplayLayout.Bands[0].Columns["Key"].Hidden = true;
cbNonEligReason.DisplayLayout.Bands[0].Columns["Value"].Header.Caption = "Noneligiblity Reason";
grdModReviews.DisplayLayout.Bands[0].Columns["reviewnum"].CellActivation = Activation.NoEdit;
grdModReviews.DisplayLayout.Bands[0].Columns["intcaseno"].Hidden = true;
grdModReviews.DisplayLayout.Bands[0].Columns["noneligibilityreason"].Hidden = true;
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].Hidden = false;
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].Header.Caption = "Date of Screen";
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].Width = 100;
grdModReviews.DisplayLayout.Bands[0].Columns["screendate"].EditorComponent = dteModRvwDate;
grdModReviews.DisplayLayout.Bands[0].Columns["eligible"].Hidden = false;
grdModReviews.DisplayLayout.Bands[0].Columns["eligible"].Header.Caption = "Eligible";
grdModReviews.DisplayLayout.Bands[0].Columns["eligible"].Width = 70;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Hidden = false;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Header.Caption =
"Reason for Noneligibility";
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Width = 250;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].EditorComponent = cbNonEligReason;
grdModReviews.DisplayLayout.Bands[0].Columns["NonEligibleReasonIDStr"].Nullable =
Infragistics.Win.UltraWinGrid.Nullable.Nothing;
}
Это достаточно большая программа, и там могут быть некоторые полезные функции в классах CslaFactoryBusinessObjects, но я думаю, что я должен научиться, как это сделать, чтобы лучше понять манипуляции с данными в WPF.
Я искал решение в течение нескольких дней и не нашел случая, подобного моему. Я просто не уверен, как работает каждый из свойств привязки и как они применяются в этом конкретном случае. Наконец пришлось бросить полотенце и сделать счет здесь. Извините за длину, но я хотел быть конкретным и показать, что я был на это некоторое время.
Пожалуйста, помогите!
Ваш первый пример заставил его работать. Кроме того, ваше объяснение (наряду с работающим примером для работы) позволило выяснить, что делает каждый из этих четырех свойств. Единственный вопрос, который я оставил, - это хороший способ сделать то, что я хочу. Из того, что я понимаю, CSLA - это все, что касается разделения слоев, с доступом к данным и пользовательским интерфейсом, насколько это возможно, для обеспечения безопасности и защиты данных. Для этого нужен адаптер для таблицы? Или я ошибочно пропускаю бизнес-уровень? – MichaelN
@MichaelN Вы правы, что CSLA разрешает (как минимум) логическое расслоение, что, в свою очередь, позволяет вам физически распределять/распределять ваш код, если это необходимо для его нужд. Тем не менее, мы сейчас входим в архитектуру решения и не зная, какие компромиссы были сделаны над другими, и, самое главное, я не хочу комментировать «что лучше». Тем не менее, ваш пример, похоже, смешивает ADO.NET + DataSet с CSLA. Если это временный переходный штраф, а если нет, поймите почему. Книги по-прежнему актуальны (Expert C# Business Objects или CSLA 4 ebooks) https://goo.gl/z17bV3 – Jaans