Если я правильно понял ваш вопрос правильно, вы будете заполнить содержимое выпадающего списка в ячейке на основе выбора выпадающего списка в другой ячейке, которая находится в той же строке DataGrid. Если да:
Первого решение (ИМО предпочтительное)
Сделать ViewModel, который представляет данные строки (простую обертку вокруг вашего объекта данных). Привяжите свойство ItemsSource целевого ComboBox к IEnumerable
-свойствам, которые вы предоставляете из своей модели просмотра. Привяжите SelectedItem из source-ComboBox к другому свойству ViewModel. Каждый раз, когда это свойство-свойство изменяется в вашей ViewModel, вы изменяете содержимое списка, предоставленного ViewModel.
Использовать для уничтожения (списка) объекта a ObservableCollection<T>
. Свойство источника зависит от вас.
Вот пример. Я вызываю класс VM (для ViewModel), но это ничего не меняет в вашем текущем решении. MVVM также может использоваться частично.
public class DataObjectVM : DependencyObject {
public static readonly DependencyProperty SelectedCategoryProperty =
DependencyProperty.Register("SelectedCategory", typeof(CategoryClass), typeof(DataObjectVM), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,delegate (DependencyObject d,DependencyPropertyChangedEventArgs e){
((DataObjectVM)d).SelectedCategoryChanged(e);
}));
ObservableCollection<ItemClass> _items=new ObservableCollection<ItemClass>();
void SelectedCategoryChanged(DependencyPropertyChangedEventArgs e) {
// Change here the contents of the _items collection.
// The destination ComboBox will update as you desire
// Do not change the _items reference. Only clear, add, remove or
// rearange the collection-items
}
// Bind the destination ComboxBox.ItemsSource to this property
public IEnumerable<ItemClass> DestinationItems {
get {
return _items;
}
}
// Bind to this property with the source ComboBox.SelectedItem
public CategoryClass SelectedCategory {
get { return (CategoryClass)GetValue(SelectedCategoryProperty); }
set { SetValue(SelectedCategoryProperty, value); }
}
}
Добавьте конструктор этого класса, который принимает ваш объект данных и сделать некоторые свойства оболочки для остальных свойств, нужно предоставить в DataGrid. Если они много, вы также можете создать одно свойство, которое предоставляет объект данных и привязку к нему напрямую. Нехорошо, но это сработает. Вы также можете (необходимо) предварительно инициализировать выбранную категорию данными из вашего бизнес-объекта. Сделайте это также и в конструкторе. В качестве источника Items для DataGrid вы предоставляете IEnumerable класса DataObjectVM, который обертывает все элементы, которые вы хотите показать.
Альтернативный способ с VisualTreeHelper
Если вы хотите сделать это руководство, прописать в коде позади обработчика для ComboBox.SelectionChangedEvent и изменения затем ItemsSource в руководстве назначения ComboBox. Бизнес-объект, который вы получите с EventArgs. Конечный ComboBox, который вы должны искать в визуальном дереве (используйте VisualTreeHelper). События могут быть подключены также, если вы используете класс DataGridTemplateColumn
и добавьте DataTemplate
с соответствующими ComboBoxes.
Но я думаю, что это действительно не очень просто сделать и может быть подвержено ошибкам. Вышеупомянутое решение намного проще.
Вот код, который вы Propably ищете:
private void CboSource_SelectionChanged(object sender, SelectionChangedEventArgs e) {
ComboBox cbo = (ComboBox)sender;
FrameworkElement currentFe = VisualTreeHelper.GetParent(cbo) as FrameworkElement;
while (null != currentFe && !(currentFe is DataGridRow)) {
currentFe = VisualTreeHelper.GetParent(currentFe) as FrameworkElement;
}
if (null != currentFe) {
List<ComboBox> list = new List<ComboBox>();
FindChildFrameworkElementsOfType<ComboBox>(currentFe,list);
// Requirement 1: Find ComboBox
foreach (ComboBox cboFound in list) {
if (cboFound.Name == "PART_CboDestination") {
// This is the desired ComboBox
// Your BO is available through cbo.Found.DataContext property
// If don't like to check the name, you can also depend on the
// sequence of the cbo's because I search them in a deep search
// operation. The sequence will be fix.
}
}
List<DataGridCell> cells = new List<DataGridCell>();
FindChildFrameworkElementsOfType<DataGridCell>(currentFe,cells);
// Requirement 2: Find Sibling Cell
foreach (DataGridCell cell in cells) {
// Here you have the desired cell of the other post
// Take the sibling you are interested in
// The sequence is as you expect it
DataGridTemplateColumn col=cell.Column as DataGridTemplateColumn;
DataTemplate template = col.CellTemplate;
// Through template.Resources you can access the CollectionViewSources
// if they are placed in the CellTemplate.
// Change this code if you will have an edit cell template or another
// another construction
}
}
}
void FindChildFrameworkElementsOfType<T>(DependencyObject parent,IList<T> list) where T: FrameworkElement{
DependencyObject child;
for(int i=0;i< VisualTreeHelper.GetChildrenCount(parent);i++){
child = VisualTreeHelper.GetChild(parent, i);
if (child is T) {
list.Add((T)child);
}
FindChildFrameworkElementsOfType<T>(child,list);
}
}
И это разметка я использовал:
<DataGrid.Columns>
<DataGridTemplateColumn Header="Source" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="PART_CboSource" SelectionChanged="CboSource_SelectionChanged" ItemsSource="!!YOUR ITEMS SOURCE!!" SelectedItem="{Binding Category}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Destination">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="PART_CboDestination"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Доступ к CollectionViewSource
Чтобы получить доступ к CollectionViewSource, поместите его в раздел ресурсов соответствующего DataTemplate, а не панели, тогда у вас будет прямой ac к ним. ИМО - это местоположение в любом случае более подходящее, чем контейнер ресурсов сетки.
Если вы dont't хотят сделать это, проверьте состояние следующего поста:
How to get logical tree of a DataTemplate
К сожалению, я не использую MVVM в этом проекте, и у меня есть опыт работы с MVVM еще. возможно ли это сделать с помощью простого WPF? поскольку мои временные ограничения не позволяют мне воссоздать весь проект как MVVM или узнать MVVM. Но да, вы хорошо поняли, это мое желание. – Shimmy
Мой вопрос касается второго варианта. моя проблема - это только часть поиска, я не знаю, как найти кузена-combobox, я не хочу иметь жестко закодированную адресную таблицу, я все равно хочу, чтобы она была динамичной ... – Shimmy
+1, Звуки хорошо, похоже, что вы приближаетесь к тому, что мне нужно, спасибо за обновление вашего ответа. Что еще не решено, так это то, что я хочу иметь CollectionViewSource в (2) DataTemplate.Resources, а не в Control. поможет мне найти ресурс CollectionViewSource. – Shimmy