Мое приложение: в магазине есть коллекция продуктов и свойство Id. Продукт имеет строковые свойства ProductCode и Description. ViewModel ссылается на один экземпляр Store. ViewModel имеет статическую коллекцию продуктов (ProductList). My View DataContext установлен в ViewModel. Диски My View хранятся через ViewModel.
Что работает: My View имеет привязку TextBlock к идентификатору магазина.
Что не работает: My View имеет DataGrid для добавления продуктов для хранения продуктов. Коллекция DataGrid для добавления продуктов для хранения продуктов позволяет мне выбрать новый ProductCode, используя столбец DataGridComboBoxColumn. Это прекрасно работает. Тем не менее, я хочу, чтобы мой выбранный ProductCode обновил DataGridTextBoxColumn, который связан с описанием продукта.
Я потратил часы на поиск в сети, и я не нашел ничего, что вполне соответствует моему сценарию, за исключением, может быть, "Пример 12" из этой ссылки, но я не получил его для работы над моим проектом: Лучший учебник ComboBox Ever
Фрагмент кода из моего представления:
<StackPanel>
<TextBlock Text="{Binding Store.Id}"/>
<DataGrid ItemsSource="{Binding Store.Products}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridComboBoxColumn
Header="ProductCode"
ItemsSource="{x:Static m:ItemsProvider.ProductList}"
SelectedValueBinding="{Binding ProductCode, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="ProductCode"
DisplayMemberPath="ProductCode"/>
<!--
I want Description for my chosen Product to pop in automatically... but how?
-->
<DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
Моя модель просмотра:
public class ViewModel : NotifyObject
{
// Constructor
public ViewModel()
{
_store = new Store() { Id = 1 };
}
// Fields
Store _store;
Product _selectedProduct;
// Properties
public Store Store {
get { return _store; }
set {
_store = value;
base.NotifyPropertyChanged("Commission");
}
}
}
Моя модель продукта:
public class Product : NotifyObject
{
// Constructor
public Product() { }
// Fields
string _productCode;
string _description;
// Properties
public string ProductCode {
get { return _productCode; }
set {
_productCode = value;
base.NotifyPropertyChanged("ProductCode");
RefreshDescription(ProductCode);
}
}
public string Description {
get { return _description; }
set {
_description = value;
base.NotifyPropertyChanged("Description");
}
}
// Private Methods
void RefreshDescription(string productCode)
{
if (ItemsProvider.ProductList.Count == 0) {
return;
}
Product product = ItemsProvider.ProductList.FirstOrDefault(p => p.ProductCode == productCode);
this.Description = (product == null ? "" : product.Description);
}
}
Моя модель магазина:
public class Store : NotifyObject
{
// Constructor
public Store()
{
Products = new ObservableCollection<Product>();
}
// Fields
int _id;
// Properties
public int Id {
get { return _id; }
set {
_id = value;
base.NotifyPropertyChanged("Id");
}
}
public ObservableCollection<Product> Products { get; set; }
}
Мой статический класс для получения списка продуктов на выбор:
public static class ItemsProvider
{
static ObservableCollection<Product> _productList = new ObservableCollection<Product>();
static ItemsProvider()
{
_productList = new ObservableCollection<Product>() {
new Product() { ProductCode = "111", Description = "a" },
new Product() { ProductCode = "222", Description = "b" },
new Product() { ProductCode = "333", Description = "c" },
new Product() { ProductCode = "444", Description = "d" }
};
}
public static ObservableCollection<Product> ProductList {
get {
return _productList;
}
}
}
Из моего измененного вопроса:
Самым значительным изменением моего кода является метод RefreshDescription, который запускается после того, как ProductCode установлен для продукта. Этот метод принимает ProductCode в качестве аргумента и запрашивает статический ProductList, чтобы найти первое сопоставление Описание. Пользователь может изменить свойство Автозаполнения Описание, если это необходимо.
Еще раз спасибо тем, кто помог мне прийти к такому выводу!
Один простой способ сделать это - поднять PropertyChanged
при изменении кода продукта, а затем выполнить поиск, чтобы получить описание:
// Properties
public string ProductCode {
get { return _productCode; }
set {
_productCode = value;
base.NotifyPropertyChanged("ProductCode");
base.NotifyPropertyChanged("Description");
}
}
public string Description {
get {
var matchingProduct = ViewModel.ProductList.FirstOrDefault(product => product.ProductCode == ProductCode);
return (matchingProduct == null ? "" : matchingProduct.Description);
}
}
Вероятно, лучшим подходом к вышеизложенному было бы определение другого класса для коллекций ProductList и Products. Первый должен быть ProductType (содержащий код продукта и описание), а последним должен быть ProductInstance (содержащий только код продукта). Затем вы можете использовать что-то вроде выше, чтобы определить описание продукта только для чтения в последнем классе.