Заполнить поле со списком коллекцией, отличной от той, к которой привязана сетка, в которой она находится

#wpf #binding

#wpf #привязка

Вопрос:

У меня есть следующий код:

 <Grid DataContext="{Binding ItemTypes}">
            ...

            <TextBlock Text="Name:" />
            <TextBox Grid.Column="2" Text="{Binding Name}" />

            <TextBlock Grid.Row="1" Text="Description:" />
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Description}" />

            <TextBlock Grid.Row="2" Text="Manufacturer:" />
            <ComboBox Grid.Column="1" Grid.Row="2" />

            <TextBlock Grid.Row="3" Text="Short Name:" />
            <TextBox Grid.Column="1" Grid.Row="3" Text="{Binding ShortName}" />
        </Grid>
  

Типы элементов, с помощью которых задается DataContext сетки, поступают из ViewModel, которая содержит еще одну коллекцию. Поле со списком производителя, которое находится внутри этой сетки, должно быть заполнено другой коллекцией. Я пробовал это:

      ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
 AncestorType=Window, AncestorLevel=1}, Path=DataContext.companies}"
  

Но это не сработало. Как я могу заставить поле со списком заполнить другую коллекцию, отличную от той, к которой привязана сетка?

Код ViewModel:

     public class ItemTypeViewModel
    {
        #region private fields
        private ICollectionView collectionView;
        private IItemTypeService itemTypeService;
        #endregion

        #region automatic properties
        public ObservableCollection<ItemTypeViewModel> ItemTypes { get; private set; }
        public IEnumerable<Company> companies { get; private set; }
        #endregion properties

        #region constructors
        public ItemTypeAdminViewModel(IItemTypeService itemTypeService)
        {
            this.itemTypeService = itemTypeService;
            Initialize();
            collectionView = CollectionViewSource.GetDefaultView(ItemTypes);
        }
        #endregion

        #region private methods
        private void Initialize()
        {
            //TODO figure out if I should I wrap in Try/Catch here
            ItemTypes = new ObservableCollection<ItemTypeViewModel>(itemTypeService.GetItemTypes());
            companies = itemTypeService.GetCompanies();
        }
        #endregion

        #region commands
        public ICommand GoToFirst
        {
            get
            {
                return new RelayCommand(() => collectionView.MoveCurrentToFirst(),
                    () => collectionView.CurrentPosition >= 1);
            }
        }

        public ICommand GoToLast
        {
            get
            {
                return new RelayCommand(() => collectionView.MoveCurrentToLast(),
                    () => collectionView.CurrentPosition < (ItemTypes.Count - 1));
            }
        }

        public ICommand NextCommand
        {
            get
            {
                return new RelayCommand(() => collectionView.MoveCurrentToNext(),
                    () => collectionView.CurrentPosition < (ItemTypes.Count - 1));
            }
        }

        public ICommand PreviousCommand
        {
            get
            {
                return new RelayCommand(() => collectionView.MoveCurrentToPrevious(),
                    () => collectionView.CurrentPosition >= 1);
            }
        }
        #endregion
    }
}
  

Ответ №1:

Предположим, что для вашей модели представления установлено значение Window.DataContext , а другая ваша коллекция MyOtherCollection является свойством в модели представления. Измените свой ComboBox на следующий:

 <ComboBox Grid.Column="1" Grid.Row="2"
          ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=DataContext.MyOtherCollection}" />
  

Комментарии:

1. Спасибо за ваш ответ, хотя я пробовал, и у меня это не работает. По-прежнему ничего не отображается.

Ответ №2:

Что назначено datacontext представления в его конструкторе. Если вы назначаете datacontext view для viewmodel посредством внедрения конструктора, вы должны иметь возможность напрямую привязывать как ItemsSource="{Binding companies}"

Комментарии:

1. XAML-код формы на самом деле является пользовательским элементом управления. Данные, которые оно получает (например, ItemTypes в таблице), поступают со страницы, которая содержит этот пользовательский элемент управления, и имеет свой набор DataContext.

Ответ №3:

Я бы сказал, просто не устанавливайте DataContext на Grid . Вместо этого привяжите каждый элемент по отдельности. Сложно давать дальнейшие советы, если вы не предоставите дополнительную информацию — в частности, о вашей виртуальной машине.

Комментарии:

1. Сетка с ее DataContext, установленным в ItemTypes (код XAML, который я опубликовал), является пользовательским элементом управления. В нем есть типы элементов, исходящие из ViewModel, на которые настроено содержащееся в нем окно. Вы все еще думаете, что установка каждого элемента обязательна?