Обновление текста TextBox при изменении значения ComboBox

1

Мое приложение: в магазине есть коллекция продуктов и свойство 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

Решено:

Самым значительным изменением моего кода является метод RefreshDescription, который запускается после того, как ProductCode установлен для продукта. Этот метод принимает ProductCode в качестве аргумента и запрашивает статический ProductList, чтобы найти первое сопоставление Описание. Пользователь может изменить свойство Автозаполнения Описание, если это необходимо.

Фрагмент кода из моего представления:

<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;
        }           
    }           
}
  • 0
    любым возможным способом вы можете опубликовать скриншот того, что вы объясняете?
  • 0
    При назначении ProductCode, изменив его в Combobox, обновите описание. Конечно, класс Product должен реализовывать InotifyPropertyChanged для того, чтобы любое изменение могло быть отражено в DataGrid, поскольку ObservableCollection не может это сделать.
Показать ещё 9 комментариев
Теги:
wpf
wpfdatagrid

2 ответа

1
Лучший ответ

Из моего измененного вопроса:

Самым значительным изменением моего кода является метод RefreshDescription, который запускается после того, как ProductCode установлен для продукта. Этот метод принимает ProductCode в качестве аргумента и запрашивает статический ProductList, чтобы найти первое сопоставление Описание. Пользователь может изменить свойство Автозаполнения Описание, если это необходимо.

Еще раз спасибо тем, кто помог мне прийти к такому выводу!

2

Один простой способ сделать это - поднять 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 (содержащий только код продукта). Затем вы можете использовать что-то вроде выше, чтобы определить описание продукта только для чтения в последнем классе.

  • 0
    Я думаю, я понял это. Вы на правильном пути, но это не работает идеально, потому что мне нужно позволить пользователю ввести другое описание, если она того пожелает. Я выложу свое решение завтра - пора домой. Спасибо МакГарнагл и @Maximus!
  • 0
    Спасибо @McGarnagle и Maximus за ваш вклад! Я проголосовал за ваш ответ и комментарий. Пожалуйста, смотрите мои комментарии в разделе «Решено» в моем вопросе. Единственное, чего не хватает в ответе МакГарнагла, это сеттер для Description; Я не хочу, чтобы пользователь мог изменить описание на другое, отличное от автоматически заполняемого значения, если оно того пожелает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню